2011-03-04 14 views
18

Estoy tratando de aprender la biblioteca STL y estoy teniendo un problema extraño. Este código se compila perfectamente:Pregunta sobre iterador vectorial en funciones de plantilla

void Show(vector<int> myvec) 
{ 
    vector<int>::iterator it; 
    cout << "Vector contains:"; 
    for(it = myvec.begin(); it < myvec.end(); it++) 
    { 
     cout << " " << *it; 
    } 
    cout << endl; 
} 

mientras éste me da un mensaje de error en tiempo de compilación:

template <class T> 
void Show2(vector<T> myvec) 
{ 
    vector<T>::iterator it; 
    cout << "Vector contains:"; 
    for(it = myvec.begin(); it < myvec.end(); it++) 
    { 
     cout << " " << *it; 
    } 
    cout << endl; 
} 

El error es:

$ g++ hello.cpp 
hello.cpp: In function ‘void Show2(std::vector<T, std::allocator<_Tp1> >)’: 
hello.cpp:19: error: expected ‘;’ before ‘it’ 
hello.cpp:21: error: ‘it’ was not declared in this scope 

Parece un error muy simple, pero No pude encontrarlo

+0

posible duplicado de [Dónde colocar la "plantilla" y "nombre de tipo" en los nombres dependientes] (http://stackoverflow.com/questions/610245/where-to-put-the-template-and-typename- on-dependent-names) – fredoverflow

+2

Es probable que haya respondido muchas veces antes, pero es difícil buscar los nombres de tipo/dependiente si no sabe que tales términos existen – Erik

+0

@FredOverflow que es un enlace muy bueno y probablemente lo lea ahora mismo. Pero, como dice @Erik, si no sabes cuál es el problema subyacente, buscarás muchos términos específicos y nunca más para el problema más general. Hice muchas búsquedas de iteradores, plantillas, vectores, STL, ... y no encontré nada. Ni siquiera sabía que existía la palabra clave 'typename' (:(sí, soy novato: P). Pensé que era solo un estúpido error de sintaxis. –

Respuesta

24

que necesita decir typename vector<T>::iterator it.

En otro aspecto, está pasando vector s por valor. Eso significa que todo el vector se copia en la llamada a la función. void Show(vector<T> const &myvec) y usar const_iterator sería más sabio.

+4

Si pasa una referencia constante, también necesita decirle que use un const_iterator. – Erik

+0

@Erik: muy bien, actualicé mi publicación. –

+0

gracias por la sugerencia. –

2

Algunos compiladores tienen problemas para detectar qué es un nombre de miembro y qué es un nombre de tipo, cuando están dentro de las plantillas. Intente escribir algo como esto en la primera línea de su cuerpo de función de plantilla.

typename vector<T>::iterator it;

+1

Correcto, pero en realidad no es un problema de compilación. El Estándar C++ exige que el compilador trate un nombre dependiente en una plantilla como miembro y no como un tipo, a menos que se use * typename *. – decltype

+1

No es "algunos compiladores". La gramática simplemente no lo permite. "Algunos compiladores" pueden adivinar el programador volviendo a intentar con typename si el análisis falla sin él y compilando * algunos * casos incorrectos. –

+0

Tienes razón. ¡Punto a favor! – CygnusX1

0

Tal vez funciona usando typename vector<T>::iterator it; Su compilador no puede saber que hay un iterador de clase interna.

16

usted necesita este:

typename vector<T>::iterator it; 

Esto le dice al compilador que vector<T>::iterator deben ser tratados como un tipo, algo que no puede asumir desde iterator depende de lo que es T.

0

En el primer caso el parámetro, aunque utiliza una plantilla, no es una plantilla, que es una clase completamente definido (vector<int>)

En el último caso, el parámetro es una plantilla del tipo T y por lo tanto requiere nombre de tipo