Erreur avec T :: iterator, où modèle paramètre T peut être vecteur ou liste
Question
Je suis en train d'écrire une fonction pour imprimer une représentation des conteneurs STL communs (vecteur, liste, etc ..). J'ai donné la fonction d'un paramètre modèle T qui, par exemple, pourrait représenter vecteur. Je vais avoir des problèmes pour obtenir un itérateur de type T.
vector<int> v(10, 0);
repr< vector<int> >(v);
...
template <typename T>
void repr(const T & v)
{
cout << "[";
if (!v.empty())
{
cout << ' ';
T::iterator i;
for (i = v.begin();
i != v.end()-1;
++i)
{
cout << *i << ", ";
}
cout << *(++i) << ' ';
}
cout << "]\n";
}
...
brett@brett-laptop:~/Desktop/stl$ g++ -Wall main.cpp
main.cpp: In function ‘void repr(const T&)’:
main.cpp:13: error: expected ‘;’ before ‘i’
main.cpp:14: error: ‘i’ was not declared in this scope
main.cpp: In function ‘void repr(const T&) [with T = std::vector<int, std::allocator<int> >]’:
main.cpp:33: instantiated from here
main.cpp:13: error: dependent-name ‘T::iterator’ is parsed as a non-type, but instantiation yields a type
main.cpp:13: note: say ‘typename T::iterator’ if a type is meant
J'ai essayé « typename T :: iterator » comme le compilateur suggéré, mais seulement eu une erreur plus cryptique.
Edit: Merci pour l'aide les gars! Voici une version de travail pour tous ceux qui veulent utiliser cette fonction:
template <typename T>
void repr(const T & v)
{
cout << "[";
if (!v.empty())
{
cout << ' ';
typename T::const_iterator i;
for (i = v.begin();
i != v.end();
++i)
{
if (i != v.begin())
{
cout << ", ";
}
cout << *i;
}
cout << ' ';
}
cout << "]\n";
}
La solution
Vous avez besoin typename
de dire au compilateur que ::iterator
est censé être un type. Le compilateur ne sait pas que c'est un type parce qu'il ne sait pas ce que T est jusqu'à ce que vous instancier le modèle. Il pourrait également se référer à certains membres de données statiques, par exemple. C'est votre première erreur.
Votre deuxième erreur est que v
est une référence-to const . Ainsi, au lieu de ::iterator
vous devez utiliser ::const_iterator
. Vous ne pouvez pas demander à un conteneur constant pour une iterator non const.
Autres conseils
Modifier T::iterator i;
à typename T::const_iterator i;
parce ::iterator
est de type T
et v
est un const &
.
Avant un type à charge admissible, vous avez besoin typename
.
Sans typename
, il y a une règle C ++ qui analyse indique que les noms dépendants qualifiés doivent être analysés comme non-types
même si elle conduit à une erreur de syntaxe.
typename
indique que le nom qui suit doit être traité comme un type. Dans le cas contraire, les noms sont interprétés comme se rapportant aux non-types.