El problema no es con gcc sino con Visual Studio, w Que acepta código que no se ajusta al estándar C++.
Ha sido respondida hasta el final en este mismo sitio, así que seré breve.
La norma requiere plantillas para ser evaluado dos veces:
- una vez en el punto de definición:
template <class T> struct Foo { void bar(); };
- una vez en el punto de instanciation:
Foo<int> myFoo;
La primera vez, todo el los nombres no dependientes serán deducibles del contexto:
- el compilador vomitar si olvidó puntuacion, se refiere a los tipos/métodos desconocidos/atributos
- el compilador seleccionará la sobrecarga de las funciones involucradas en este punto
Debido sintaxis de C++ es ambigua, es necesario para ayudar al analizador en esta fase y utilizar las palabras clave template
y typename
de forma adecuada para desambiguar manualmente.
Desafortunadamente, Visual Studio no cumple, y solo implementa la segunda evaluación (en el momento de la instanciación).La ventaja para los perezosos es que se puede escapar sin esos extras template
y typename
palabras clave, la desventaja es que su código está mal formado y no es portátil ...
Ahora viene la parte divertida:
void foo(int) { std::cout << "int" << std::endl; }
template <class T> void tfoo(T i) { foo(i); }
void foo(double) { std::cout << "double" << std::endl; }
int main(int argc, char* argv[])
{
double myDouble = 0.0;
tfoo(myDouble);
return 0;
}
Compilado con gcc, emite int
.
Compilado con Visual Studio, emite double
.
Problema? Cualquier persona que reutilice el mismo símbolo que usa en su código de plantilla en VS podría pisarle el pie y estropear su implementación si su símbolo aparece entre la inclusión de su código de plantilla y el momento en que realmente usa el código de la plantilla ... ¿no es así? gracioso :/ ?
Ahora, para su código:
template<typename T>
class Derived : public Base<T>
{
public:
void foo() { this->t = 4; this->get(); }
};
El this
indica que el nombre que sigue es un nombre dependiente, es decir, que depende de T
(que no es evidente cuando el símbolo aparece solo). El compilador, por lo tanto, esperará la instanciación y verá si para el tipo particular que instancia la plantilla Base<T>
contiene esos métodos. No es obligatorio, ya que podía perfectamente especializarse Base
:
// It's non-sensical to instanciate a void value,
template <>
class Base<void> {};
Y así Derived<void>
no debería compilar;)
Un vínculo obligatorio a C++ FAQ: http://www.parashift.com/c++-faq- lite/templates.html # faq-35.19 – UncleBens
Respuesta corta: porque gcc cumple con los estándares y (sorprendentemente) con Visual C++ no? –