Errore con T :: iterator, dove modello parametro T potrebbe essere vector o l'elenco
Domanda
Sto cercando di scrivere una funzione per stampare una rappresentazione dei contenitori comuni STL (vettore, lista, ecc ..). Ho dato la funzione di un parametro di template T, che, per esempio, potrebbe rappresentare vettore. Sto avendo problemi per ottenere un iteratore di tipo 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
ho provato 'typename T :: iterator' come il compilatore ha suggerito, ma ottenuto solo un errore più criptico.
Edit: Grazie per l'aiuto ragazzi! Ecco una versione di lavoro per chi vuole utilizzare questa funzione:
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";
}
Soluzione
È necessario typename
per dire al compilatore che ::iterator
si suppone che sia un tipo. Il compilatore non sa che si tratta di un tipo, perché non sa che cosa è T fino a quando si crea un'istanza del modello. Si potrebbe anche riferirsi a qualche membro di dati statici, per esempio. Questo è il tuo primo errore.
Il secondo errore è che v
è un riferimento-to- const . Così, invece di ::iterator
è necessario utilizzare ::const_iterator
. Non si può chiedere un contenitore costante per un iteratore non const.
Altri suggerimenti
Cambia T::iterator i;
a typename T::const_iterator i;
perché ::iterator
è di tipo T
e v
è un const &
.
Prima di un tipo dipendenti qualificati, è necessario typename
.
Senza typename
, c'è un C ++ parsing regola che dice che i nomi dipendenti qualificati dovrebbero essere analizzati come non-types
anche se porta a un errore di sintassi.
typename
afferma che il nome che segue deve essere considerato come un tipo. In caso contrario, i nomi vengono interpretati per riferirsi a non-tipi.