2010-09-17 6 views
6

Sto provando a scrivere una funzione per stampare una rappresentazione di contenitori STL comuni (vettore, elenco, ecc.). Ho dato alla funzione un parametro di modello T che, ad esempio, potrebbe rappresentare un vettore. Sto avendo problemi per ottenere un iteratore di tipo T.Errore con T :: iterator, dove il parametro template T potrebbe essere vettoriale <int> o lista <int>

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"; 
} 

...

[email protected]:~/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 cercato 'typename T :: iterator' come il suggerito dal compilatore, ma ha ottenuto solo un errore più criptico.

Modifica: 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"; 
} 
+0

Come pubblicare il messaggio di errore "più criptico"? –

+4

btw, potresti voler sostituire v.end() - 1 con qualcos'altro che anche gli iteratori non-RandomAccess supportano. – sellibitze

risposta

18

È necessario typename per dire al compilatore che ::iterator si suppone essere un tipo. Il compilatore non sa che è un tipo perché non sa cosa sia T fino a quando non istanziate il modello. Potrebbe anche fare riferimento ad alcuni membri di dati statici, ad esempio. Questo è il tuo primo errore.

Il secondo errore è che v è un riferimento a const. Quindi, invece di ::iterator devi usare ::const_iterator. Non è possibile chiedere un contenitore costante per un iteratore non const.

+0

Chi ha downvoted questa risposta? La risposta è corretta –

+0

Non tanto che il compilatore non sappia cosa sia ':: iterator', ma lo standard lo richiede per interpretarlo come non-type, dato che è ben inserito nel messaggio di errore:" nome-dipendente ''T :: iterator' 'viene analizzato come non-type, ma l'istanza produce un tipo " – visitor

+2

I see. Quindi, questo taglio di capelli giustifica un downvote. – sellibitze

3

Change T::iterator i; a typename T::const_iterator i; perché ::iterator è di tipo T e v è un const &.

Prima di un tipo dipendente qualificato, è necessario typename. Senza typename, esiste una regola di analisi C++ che dice che i nomi dipendenti qualificati devono essere analizzati come non-types anche se causano un errore di sintassi.

typename afferma che il nome che segue deve essere considerato come un tipo. Altrimenti, i nomi vengono interpretati come riferiti a non-tipi.

Problemi correlati