2011-02-03 16 views
7

Ahh, C++ plantillas ...¿Cuál es el significado de este error 'falta de plantilla argumentos' C++

The code I see,
makes sense to me,
but GCC...
it disagrees.

El código siguiente se compila y se ejecuta como se esperaba, pero si se elimina el comentario de que #define, se obtiene el error que no entiendo El símbolo iterator todavía tiene una sola cosa a la que puede hacer referencia: typedef en la superclase. Así que supongo que tengo dos preguntas: 1. ¿Qué significan los errores? 2. ¿Cuál es la mejor manera de solucionarlos?

#include <map> 
#include <string> 
#include <cstdio> 

using namespace std; 

// #define WITH_TEMPLATE 1 

#ifdef WITH_TEMPLATE 
template <class C> 
struct MyClass : public map<string, C> 
#else 
struct MyClass : public map<string, int> 
#endif 
{ 
    bool haskey(const string &s) 
    { 
     iterator it = find(s); 
     return (it != end()); 
    } 
}; 

int main() 
{ 
#ifdef WITH_TEMPLATE 
    MyClass<int> m; 
#else 
    MyClass m; 
#endif 
    m["test"] = 10;  
    printf("%d %d\n", m.haskey("test"), m.haskey("no")); 
} 

errores de GCC:

temp.cc: In member function ‘bool MyClass::haskey(const std::string&)’:
temp.cc:18: error: missing template arguments before ‘it’
temp.cc:18: error: expected `;' before ‘it’
temp.cc:19: error: ‘it’ was not declared in this scope
temp.cc:19: error: there are no arguments to ‘end’ that depend on a template parameter, so a declaration of ‘end’ must be available
temp.cc:19: error: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

+0

¿Ha intentado string :: iterador? – Lordalcol

Respuesta

4

Es necesario cambiar sus MyClass :: método Haskey también.

bool haskey(const string &s) 
{ 
    typename MyClass<C>::iterator it = this->find(s); 
    return (it != this->end()); 
} 

Explicación de tal comportamiento se encuentra en la sección "Nombre de búsqueda, plantillas, y el acceso a los miembros de las clases base" en la http://physics.ucsd.edu/students/courses/winter2008/physics141/manuals/rhel-gcc-en-4/c---misunderstandings.html (enlace desde el comentario de otra respuesta, por si acaso).

entero ejemplo de código fijo: http://ideone.com/G7Rty

+1

Gracias. Marcaría esto como la respuesta, pero no explica el motivo del error. Esa explicación está en un enlace en la otra respuesta. –

+0

Este enlace está roto o detrás de un muro de pago. ¿Alguna referencia actualizada? –

3
iterator it = find(s); 
return (it != end()); 

Esta línea debe ser lo más,

#ifdef WITH_TEMPLATE 
      typename map<string, C>::iterator it = this->find(s); 
      return (it != this->end()); 
#else 
      map<string, int>::iterator it = find(s); 
      return (it != end()); 
#endif 
+1

Olvidó 'typename'. –

+0

@Nawaz ¿así que la clase derivada no puede ver typedefs de clase base? – UmmaGumma

+0

@Ashot: cuando la clase base es una plantilla, el compilador no puede saber en tiempo de análisis si la clase contiene ese tipo dedef o no. Por lo tanto, debe usar typename explícitamente para hacer referencia a los tipos. – Puppy

Cuestiones relacionadas