Il problema non è con gcc ma con Visual Studio, w accetta il codice che non è conforme allo standard C++.
E 'stato risposto in tutto e per tutto su questo sito così sarò breve.
La norma richiede modelli da valutare due volte:
- una volta al punto di definizione:
template <class T> struct Foo { void bar(); };
- una volta al punto di instanciation:
Foo<int> myFoo;
La prima volta, tutte le Nomi non dipendenti sono deducibili dal contesto:
- il compilatore vomitare se hai dimenticato la punteggiatura, si riferisce a sconosciuti tipi/metodi/attributi
- il compilatore selezionerà il sovraccarico per le funzioni interessate a questo punto
perché la sintassi C++ è ambiguo, è necessario per aiutare il parser in questa fase e utilizzare le parole chiave template
e typename
in modo appropriato per disambiguare manualmente.
Sfortunatamente, Visual Studio non è conforme e implementa solo la seconda valutazione (al punto di instanciazione).Il vantaggio per i più pigri è che si può ottenere via senza quelli extra template
e typename
parole chiave, lo svantaggio è che il codice è mal formata e non portatili ...
Ora per la parte divertente:
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;
}
Compilato con gcc, emette int
.
Compilato con Visual Studio, emette double
.
Il problema? Chiunque riutilizzi lo stesso simbolo che fai nel tuo codice template in VS potrebbe fare un passo falso alla tua implementazione se il loro simbolo appare tra l'inclusione del tuo codice template e il momento in cui effettivamente usano il codice template ... non è vero? divertente :/ ?
Ora, per il codice:
template<typename T>
class Derived : public Base<T>
{
public:
void foo() { this->t = 4; this->get(); }
};
Il this
indica che il nome che segue è un nome dipendente, vale a dire che dipende da T
(che non è evidente quando il simbolo appare solo). Il compilatore attenderà quindi l'instanciazione e vedrà se per il particolare tipo che installi il modello Base<T>
contiene quei metodi. Non è obbligatorio, da quando ho potuto specializzarmi perfettamente Base
:
// It's non-sensical to instanciate a void value,
template <>
class Base<void> {};
E così Derived<void>
non dovrei compilare;)
Un collegamento obbligatorio per C++ FAQ: http://www.parashift.com/c++-faq- lite/templates.html # faq-35.19 – UncleBens
Risposta breve: perché gcc è conforme agli standard e (sorprendentemente) Visual C++ non lo è? –