Dentro de un C++ función foo plantilla(), una llamada a :: bar (TT *) da el siguiente error bajo gcc 4.4.3:En la función de plantilla de C++, ¿por qué la llamada a función dependiente da el error "no declarado"?
g++ -o hello.o -c -g hello.cpp
hello.cpp: In function 'void foo(std::vector<TT*, std::allocator<TT*> >&)':
hello.cpp:8: error: '::bar' has not been declared
Aquí está el código erróneo:
// hello.cpp
#include <vector>
template<typename TT> void foo(std::vector<TT*> &vec)
{
TT *tt;
::bar(tt);
vec.push_back(tt);
}
class Blah
{
};
void bar(Blah *&)
{
}
int main(int argc, char *argv[])
{
std::vector<Blah*> vec;
foo(vec);
return 0;
}
C++ distingue entre símbolos que dependen del parámetro de plantilla (TT, aquí) y aquellos símbolos que son independientes y pueden evaluarse inmediatamente.
Claramente, el compilador cree que mi llamada :: bar (TT *) es independiente y trata de resolverlo inmediatamente. Igualmente, la llamada a función es, depende de TT porque la llamada de función toma un parámetro de tipo TT *, por lo que el compilador debe esperar hasta la instanciación foo (vec) para resolver :: barra (TT *).
¿Es esto un error de gcc o me falta algo sutil sobre las plantillas de C++?
EDITAR: aquí hay un ejemplo un poco más complicado con dos versiones de :: bar() para aclarar que el orden de la declaración no es el problema con mi problema. Al analizar la plantilla, el compilador tiene no forma de saber si main() abajo creará la función de plantilla con TT = Blah o con TT = Argh. Por lo tanto, el compilador no debe dar un error hasta
línea 35
línea 28 como muy pronto (si es que lo hace). Pero el error se da para
línea 8
línea 16.
EDIT # 2: mejoró este ejemplo.
EDIT # 3: se han agregado correcciones a este ejemplo para que funcione como se desee. La barra (tt) ahora se refiere correctamente a la barra (Blah *). Justificación dada a continuación. (Gracias a todos).
// hello.cpp
#include <vector>
class XX {};
void bar(XX*) {}
class CC {
public:
void bar();
void bar(int *);
void bar(float *);
template<typename TT> static void foo(std::vector<TT*> &vec);
};
template<typename TT>
void CC::foo(std::vector<TT*> &vec) {
using ::bar;
TT *tt;
bar(tt);
vec.push_back(tt);
}
class Argh {};
void bar(Argh *&aa) { aa = new Argh; }
class Blah {};
void bar(Blah *&bb) { bb = new Blah; }
int main(int argc, char *argv[]) {
std::vector<Blah*> vec;
CC::foo(vec);
return 0;
}
el error dice que ":: bar" no se ha declarado algo así como "no hay prototipo correspondiente" ... ¿tal vez la barra realmente no está declarada? esto es una suposición –
"Con la misma claridad, esa llamada a función depende de TT porque la llamada a función toma un parámetro de tipo TT *, por lo que el compilador debe esperar hasta la instanciación foo (vec) para resolver :: barra (TT *) . ". Incorrecto. Los meros nombres ":: barra" y "barra" no son dependientes. Existe una regla especial para hacer dependientes los nombres que de otro modo serían dependientes cuando se usan como unction, que es el texto @Chris quotes, y que solo se aplica a nombres no calificados. Lo que hay que hacer en la instanciación de todos modos es la resolución de sobrecarga en la declaración encontrada [s] con los argumentos dados (dependientes). –
Ya he mencionado esto a continuación, pero esto parece estar en desacuerdo con usted: Stroustrup TC++ PL Sp Ed, Sección C.13.8.1, Nombres Dependientes: "Básicamente, el nombre de una función llamada es dependiente si es obviamente dependiente de mirando sus argumentos o sus parámetros formales ". Según ese criterio, ':: bar' es" obviamente dependiente ". –