GNT sans publicité, site mobile, fonctionnalitées exclusives...

Erreur de compilation d'un itérateur de map avec GCC

Le
Nicolas
Bonjour,

En essayant d'aider un ami sur un petit code C++, j'ai eu une erreur de
compilation de son code avec G++ sous GNU/Linux (versions 3.4.6 et
4.1.1). Le code est compilé par ICC 9.0 sous GNU/Linux et Microsoft CL
14.00.50727.42 (fourni avec Visual Studio 2005). Dans les deux cas
réussis, l'exécution me donne le résultat attendu.
Le message renvoyé par G++ me retient de poster un rapport de bug tout
de suite, car je ne suis pas sûr de ne pas avoir fait d'erreur dans ce
programme :



#include <iostream>
#include <map>
#include <string>

template <class T>
class C
{
public:
void listAll() {
for(std::map<std::string, T>::iterator i = box.begin();
i != box.end(); i++){
std::cout << i->first << " > "
<< i->second << std::endl;
}
}
std::map<std::string, T> box;
};

int main(int argc, char *argv[])
{

C<int> c0;
c0.box["abc"] = 123;
c0.box["def"] = 456;
c0.listAll();

C<std::string> c1;
c1.box["xx"] = "ref'd by xx";
c1.box["yy"] = "ref'd by yy";
c1.listAll();

return 0;
}



Avec ICC et CL, le binaire généré produit la sortie suivante :
abc > 123
def > 456
xx > ref'd by xx
yy > ref'd by yy

L'erreur de compilation par G++ se situe au niveau de l'itérateur sur le
map<std::string, T> :

test.cc: In member function `void C<T>::listAll()':
test.cc:10: erreur: expected `;' avant « i »
test.cc: In member function `void C<T>::listAll() [with T = int]':
test.cc:23: instantiated from here
test.cc:10: erreur: nom dépendant « std::map<std::basic_string<char,
std::char_traits<char>, std::allocator<char>
>,T,std::less<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >,std::allocator<std::pair<const
std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
T> > >::iterator » est analysé comme un non type, mais son instantiation
le rend comme un type
test.cc:10: note: utiliser « typename std::map<std::basic_string<char,
std::char_traits<char>, std::allocator<char>
>,T,std::less<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >,std::allocator<std::pair<const
std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
T> > >::iterator » si un type est désiré

Le message "::iterator est analysé comme un non type" me rend perplexe,
car c'est bien comme un type que je veux l'utiliser.
Il me semble alors que le conseil d'utiliser typename est destiné aux
codeurs de map, non ?

Pourriez-vous m'éclairer sur cette erreur ?

Merci,

Nicolas.
Lire les 9 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
loufoque
Le #286194

Pourriez-vous m'éclairer sur cette erreur ?


Je suppose que cela fonctionne si tu remplaces "std::map<std::string,
T>::iterator i" par "typename std::map<std::string, T>::iterator i" ?

Nicolas
Le #286193
loufoque wrote:

Pourriez-vous m'éclairer sur cette erreur ?


Je suppose que cela fonctionne si tu remplaces "std::map<std::string,
T>::iterator i" par "typename std::map<std::string, T>::iterator i" ?



En effet, merci !

L'explication de typename dans mon Stroustrup comporte justement un
exemple quasiment identique, avec vector Cela dit, il est précisé que "le compilateur pourrait examiner la
déclaration de vector<> afin de déterminer si l'itérateur (iterator)
dans vector qualificatif est un paramètre type." (afin de repousser le test jusqu'au
moment où il est possible de le déterminer).
Il est précisé : "Cela constituerait toutefois une extension de langage
non standard".

Qui a raison dans ce cas ? GCC qui ne va pas chercher plus loin et qui
me demande un typename, ou ICC et CL qui se débrouillent pour comprendre
ce que je veux dire ? D'après les explications du livre, je dirais GCC,
mais est-ce standardisé ?

Nicolas.


Franck Branjonneau
Le #286148
Nicolas
[ Absence de typename sur type dependant ]

L'explication de typename dans mon Stroustrup [...].
Il est précisé : "Cela constituerait toutefois une extension de langage
non standard".


Voilà ;-)

Qui a raison dans ce cas ? GCC qui ne va pas chercher plus loin et qui
me demande un typename, ou ICC et CL qui se débrouillent pour comprendre
ce que je veux dire ? D'après les explications du livre, je dirais GCC,
mais est-ce standardisé ?


Oui, g++ a raison. Le typename implicite est déprécié, en accord avec
le standard, depuis gcc-3.4 : « You must now use the typename and template keywords to disambiguate
dependent names, as required by the C++ standard. »

--
Franck Branjonneau

kanze
Le #286144
Franck Branjonneau wrote:
Nicolas écrivait:

[ Absence de typename sur type dependant ]

Qui a raison dans ce cas ? GCC qui ne va pas chercher plus
loin et qui me demande un typename, ou ICC et CL qui se
débrouillent pour comprendre ce que je veux dire ? D'après
les explications du livre, je dirais GCC, mais est-ce
standardisé ?


Oui, g++ a raison. Le typename implicite est déprécié,


Ne tombons pas dans le même abus du langage que Microsoft. Le
typename implicit n'a pas été déprécié par ISO. Pour la simple
raison qu'en ce qui concerne ISO, il n'a jamais existé.

en accord avec le standard, depuis gcc-3.4 :
the typename and template keywords to disambiguate dependent
names, as required by the C++ standard. »


Je crois en effet que la norme exige une diagnostique. Qui
pourrait n'être qu'un avertissement ; si le compilateur a
accepté le code sans le typename avant (ce qui est le cas de
tous les compilateurs, je crois), il serait logique qu'il y a un
certain nombre de versions où il continue de l'accepter avec un
avertissement (et une option pour qu'il le réfuse), puis des
versions où c'est une erreur, mais il y a une option pour ne le
traiter que comme avertissement, et seulement au bout de longues
années, on en supprime le supporte complétement.

Selon la façon que sont implémenté les templates, en revanche,
ce n'est pas toujours évident de faire comme ça. Il faudrait
prèsque maintenir deux parseurs en parallel, ce qui implique un
boulot monstreux.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Franck Branjonneau
Le #286141
"kanze"
Franck Branjonneau wrote:
Nicolas écrivait:

[ Absence de typename sur type dependant ]

Qui a raison dans ce cas ? GCC qui ne va pas chercher plus
loin et qui me demande un typename, ou ICC et CL qui se
débrouillent pour comprendre ce que je veux dire ? D'après
les explications du livre, je dirais GCC, mais est-ce
standardisé ?


Oui, g++ a raison. Le typename implicite est déprécié,


Ne tombons pas dans le même abus du langage que Microsoft. Le
typename implicit n'a pas été déprécié par ISO. Pour la simple
raison qu'en ce qui concerne ISO, il n'a jamais existé.

en accord avec le standard, depuis gcc-3.4 :
the typename and template keywords to disambiguate dependent
names, as required by the C++ standard. »



C'est toi qui abuse. Je n'ai pas parlé d'ISO, seulement de g++.

Je crois en effet que la norme exige une diagnostique.


Tu n'abuses pas que du langage ;-) Qui parle de diagnostic ?

Je doute que la norme exige un diagnostic. Mon argument est purement
logique : si tel était le cas alors les compilateurs pourraient
implémenter le typename implicite.

Qui pourrait n'être qu'un avertissement ; si le compilateur a
accepté le code sans le typename avant (ce qui est le cas de tous
les compilateurs, je crois), il serait logique qu'il y a un certain
nombre de versions où il continue de l'accepter avec un
avertissement (et une option pour qu'il le réfuse), puis des
versions où c'est une erreur, mais il y a une option pour ne le
traiter que comme avertissement, et seulement au bout de longues
années, on en supprime le supporte complétement.


g++ n'a-t-il pas été progressif (avec des durées qui s'expriment en
mois) ?

Selon la façon que sont implémenté les templates, en revanche,
ce n'est pas toujours évident de faire comme ça. Il faudrait
prèsque maintenir deux parseurs en parallel, ce qui implique un
boulot monstreux.


Standard conformance
« Non-conforming legacy code that worked with older versions of GCC
may be rejected by more recent compilers. There is no command-line
switch to ensure compatibility in general, because trying to parse
standard-conforming and old-style code at the same time would render
the C++ frontend unmaintainable. However, some non-conforming
constructs are allowed when the command-line option -fpermissive is
used. »

--
Franck Branjonneau



Publicité
Suivre les réponses
Poster une réponse
Anonyme