Ok. Bah je sais pas quel compilo et quelle version de C++ tu utilises, parce que là non seulement ton code n'est syntaxiquement pas correct, mais en plus ça n'est pas censé linker.
Version imprimable
Ok. Bah je sais pas quel compilo et quelle version de C++ tu utilises, parce que là non seulement ton code n'est syntaxiquement pas correct, mais en plus ça n'est pas censé linker.
Mais je trouves que tu devrais plutôt faire comme ça :
Code:
1
2
3
4
5
6 // header.h #ifndef TOTO #define TOTO int a; #endif
Code:
1
2
3 // a.h #include "header.h"
Code:
1
2
3 //a.cpp #include "a.h"
Code:
1
2
3 //b.h #include "a.h"
Code:
1
2
3 //b.cpp #include "b.h"
Moi je fais comme ça est ça fonctionne.
J'ai vraiment pas envie de te vexer, mais non.
Teste ton code, le link va échouer.
Mais bon, vu que tu n'en fais qu'à ta tête, je sais très bien que tu ne le feras pas, donc tant pis pour toi, ça aurait été une occasion pour toi de comprendre la compilation et le linkage.
Au passage, il sert à quoi a.h ? Pourquoi b.h ? Pourquoi b.h inclut a.h ?
Clairement, Lolilolight, tu ne sais pas ce qu'est l'édition de liens (le linkage), ni une unité de compilation.
Va lire un petit cours sur le sujet, ça te fera du bien. On en a plusieurs sur le site.
Ton code n'ayant même pas de main, il ne risque pas d'être lié, vu que tu va au mieux te manger un "missing symbol int main()".
Par ailleurs, tu as conscience que des gens qui ont plusieurs points par message et plus de message que toi ont probablement plus d'expertise que toi?
PS: c'est la dernière fois que je te réponds dans ce sujet, nous n'avons pas à faire montre de colère, et je risque d'y tomber.
Car dans a.cpp tu auras ainsi la définition du header dans la même unité de compilation. (et non plus dans 2 unités de compilation différentes)
Vu que a.cpp va include a.h qui lui même va include b.h qui va inclure ton header.
Oui bon tant pis je laisse béton, je vois pas du tout ou se situe le problème et je ne vois aucun intérêt à vouloir faire ça, pour moi il y a moyen de faire ça simplement et je trouve que vous compliquer le problème inutilement, je vais pas tourner autour du pot plus longtemps. (Suffit juste de chercher un peu)
Et non je n'ai pas mit de main, mais ça il suffit d'en rajouter un.
Le sytème de point je m'en passerai, quand t'a fais du c++ pendant plus de 5 ans t'a pas besoin de points. (C'est un système pour les gamins ça qui s'amusent à te retirer des points par plaisir comme j'ai tant vu sur les forums sans même comprendre le problème)
Ah bon. En lisant le code j'aurais plutôt dit a.cpp inclut a.h qui inclut header.h. Peu importe.
J'ai beau retourner ta première phrase dans tous les sens, soit je la comprends pas, soit j'en comprends que t'as compris ni le système d'inclusion, ni la compilation, ni l'édition de liens.
Idem ici.
Parle donc à un mur, tu verras quel effet ça fait.
Je te rappelle quand même qu'on est pas les premiers à t'en faire la remarque. Si tu veux te mettre à dos ceux à qui tu demandes de l'aide (ou à qui tu la proposes), t'es sur le bon chemin.
Ok je stop la discussion ici, mais merci de ne plus vouloir m'aider ou bien de poster des solutions sans comprendre vraiment le problème, car, ça aussi ça m'énerve. (Maintenant retirer moi des points hein, je m'en fou, vous voyez bien que moi je le fais pas pour vous donc là on vois bien la reconnaissance)
Si j'ai bien compris, le problème est que la conséquence de simplement définir les variables (tableau et taille) dans un fichier source particulier, et les déclarer dans un header, cette conséquence étant que la taille n'est pas une constante connue à la compilation mais est seulement connue à l'édition de liens, semble considérée ici comme une conséquence inacceptable.
Probablement parce que la problématique inclut l'utilisation de la taille dans des contextes qui nécessitent une constante connue à la compilation (tableaux, templates, switch/case...)
En même temps pourquoi vouloir utiliser un tableau si on ne connaît pas la taille en compilation (mais que à l'édition des liens) ?
Ca n'a pas de sens, autant utiliser un std::vector dans se cas là.
Si l'on n'a pas accès à C++11, utiliser un tableau est le seul moyen d'avoir quelque chose qui s'initialise "statiquement" (par manque d'un meilleur mot) vu qu'il faut C++11 pour utiliser la syntaxe {} sur les vecteurs.
Ca, ce n'est pas vrai, il y a boost:initializer qui le permet.
Ou ma petite solution inspirée, mais qui requiert une copie de vecteur.
Il "suffit" de créer un opérateur qui fait un push_back avec chainage.
Bon j'ai essayé ce code et il fonctionne, pas besoin de boost::initializer et companie.
Ca m'affiche bien 3 dans le main, qui est la taille du tableau.
Code:
1
2
3
4
5
6
7
8
9
10
11 #ifndef TEST_HPP #define TEST_HPP struct Test { static const char* tab; static const int size; }; static const char t[] = {'a', 'b', 'c'}; const char* Test::tab = t; const int Test::size = sizeof(t); #endif
Code:
1
2
3
4
5
6 #include "test.hpp" #include <iostream> int main (int argv, char* argc) { std::cout<<Test::size<<std::endl; }
C'est bien ça que tu voulais avoir, ça m'a prit même pas 2 minutes pour trouver le lien.
PS : il y a moyen de faire mieux je pense en virant la variable globale et en appelant une méthode statique qui initialise le tableau.
Ça linke, ça, quand tu as plusieurs fichiers source?
Non, mais bon rien ne t'empêche de l'initialiser dans une unité de compilation à part :
Code:
1
2
3
4
5
6
7
8
9
10 //test.h #ifndef TEST_HPP #define TEST_HPP struct Test { static const char* tab; static const int size; }; #endif
Code:
1
2
3
4
5
6 //test.cpp #include "test.hpp" static const char t[] = {'a', 'b', 'c'}; const char* Test::tab = t; const int Test::size = sizeof(t);
Code:
1
2
3
4
5
6
7 //main.cpp #include "test.hpp" #include <iostream> int main () { std::cout<<Test::size<<std::endl; }
L'initialiser dans une seule unité de compilation est suffisant! (Le faire dans plusieurs donne une erreur de linkage)
Donc soit tu l'initialise dans le fichier test.cpp ou bien dans le fichier main.cpp.
C'est ce que j'ai proposé il y a longtemps.
Et on en revient au problème que je cite: Le client veut utiliser Test::size dans un template, tableau ou switch, et ne peut pas.
Ha bon ???
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #ifndef TEST_HPP #define TEST_HPP #include <iostream> struct Test { static const char* tab; static const int size; }; struct A { A() { switch(Test::size) { case 0 : std::cout<<"size : "<<Test::size<<std::endl; break; case 1 : std::cout<<"size : "<<Test::size<<std::endl; break; case 2 : std::cout<<"size : "<<Test::size<<std::endl; break; case 3 : std::cout<<"size : "<<Test::size<<std::endl; break; } } }; #endif
Code:
1
2
3
4
5 #include "test.hpp" static const char t[] = {'a', 'b', 'c'}; const char* Test::tab = t; const int Test::size = sizeof(t);
Code:
1
2
3
4
5
6
7 #include "test.hpp" #include <iostream> int main () { std::cout<<Test::size<<std::endl; A a; }
Pour passer une constante entière à un template tu ne peux pas le faire directement (et même en c++11 il n'y a pas moyen de le faire, j'ai essayé de lire une constante entière dans un fichier ou encore retourner la taille d'un tableau et la mettre dans une constexpr pour la passé en paramètre template ça n'a pas marché.)
La solution est d'utiliser un switch.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 #include "test.hpp" #include <iostream> int main () { std::cout<<Test::size<<std::endl; switch(Test::size) { case 0 : {A<0> a;} break; case 1 : { A<1> a;} break; case 2 : { A<2> a;} break; case 3 : { A<3> a;} break; default : std::cout<<"invalid size!"<<std::endl; } }
Citation:
Envoyé par Medinoc
Ou comment taper complètement à côté de la plaque...:ptdr:Citation:
Envoyé par Lolilolight
Dans un switch, ce sont les case qui exigent des constantes connues à la compilation...:roll:
@Lolilolight :
Lorsque Médinoc dit que cela ne peut pas être utilisé dans un switch/template ou autre, c'est dans le cas où, votre template/switch n'est pas dans le même fichier que là, où vous déterminez Test::size.
On en revient aux problème d'édition de lien, d'unité de compilation et les problèmes auxquels j'avais fait face, en page une.
Au final, vous êtes revenu, en page 3, à la solution que j'ai proposé en page une et pour laquelle, je n'arrivais pas à saisir pourquoi cela marchait. En effet, mon premier test était un test minimaliste où j'avais tout mis dans la même unité de compilation et donc, que j'avais aucune soucis de disponibilité des variables. Mais, les soucis reviennent, lorsque vous voulez utiliser sizeof(Test::tableau) dans plusieurs autres fichiers.
De plus, il faut faire attention à ne pas mettre dans le .h les initialisations, sinon, elles sont compilés plusieurs fois (dans chaque .o d'un .c utilisant le .h en question). C'est une erreur pourtant classique dû à la séparation de la compilation des différent .c.
Pourquoi est ce que tu voudrais mettre le sizeof dans plusieurs fichiers ?
Même le c++11 ne fait pas ça.
Ca, c'est à éviter à tout prit!
Le sizeof doit se faire uniquement là ou tu déclare ton tableau, sinon, ça ne renverra pas la bonne taille ou pire, ça ne compilera pas.
Car le pointeur sur le tableau ne contient que l'adresse du 1er élément du tableau, pas tout le tableau, la seule solution est de sauvegarder la taille tu tableau dans une variable lors de l'initialisation du tableau.
Ou alors tu fait une liste chaînée et un itérateur comme la classe std::vector pour compter le nombres d'éléments dans ton tableau en initialisant cette liste à partir d'un tableau.
De plus tu ne peux pas faire une fonction qui retourne un tableau en c++, t'es oubligé de convertir le tableau en un pointeur.
Tu as perdu.
Plusieurs solutions ont été proposées.
Oui, avec boost. (M'enfin bon passer par une librairie externe pour faire se genre de chose ou même une solution sans utilisé boost je trouve ça très moyen)
Le coup du sizeof, dans chaque fichier était inévitablement une erreur et même, la grande erreur, mais sur le coup, je n'avais pas du tout compris ce que le compilateur me disais.
Ça ne compilera simplement pas.Citation:
Le sizeof doit se faire uniquement là ou tu déclare ton tableau, sinon, ça ne renverra pas la bonne taille ou pire, ça ne compilera pas.
Ok dis comme ça, je comprend mieux.
Il me disait
Comme quoi, il ne peut pas appliquer de sizeof sur le type que je viens de lui passer (car celui est incomplet).Citation:
error: invalid application of ‘sizeof’ to incomplete type ‘const char* []’
Effectivement, ce n'est pas clair.
Je n'avais jamais réalisé que T [] n'est pas un type complet sans la taille.
Bonne continuation!
Je sais pas si ça a été proposé, mais dans un tel cas, solution extrême : un define et un static_assert !:aie: