La versione breve che è necessario fare typename X::Y
ogni volta che X è o dipende da un parametro di modello. Fino a quando X è noto, il compilatore non può dire se Y è un tipo o un valore. Quindi devi aggiungere typename
per specificare che si tratta di un tipo.
Ad esempio:
template <typename T>
struct Foo {
typename T::some_type x; // T is a template parameter. `some_type` may or may not exist depending on what type T is.
};
template <typename T>
struct Foo {
typename some_template<T>::some_type x; // `some_template` may or may not have a `some_type` member, depending on which specialization is used when it is instantiated for type `T`
};
Come sbi sottolinea nei commenti, la causa dell'ambiguità è che Y
potrebbe essere un membro statico, un enum o una funzione. Senza conoscere il tipo di X
, non possiamo dirlo. Lo standard specifica che il compilatore dovrebbe assumere che è un valore a meno che non sia etichettato esplicitamente un tipo utilizzando la parola chiave typename
.
E sembra che i commentatori vogliono davvero di citare un altro caso relativo così:;)
Se il nome dipendente è un modello di membro di funzione, e si chiama con un argomento modello esplicito (foo.bar<int>()
, per esempio), è necessario aggiungere la parola chiave template
prima del nome della funzione, come in foo.template bar<int>()
.
Il motivo per questo è che senza la parola chiave modello, il compilatore presuppone che bar
sia un valore e che si desideri richiamare l'operatore minore di (operator<
).
Vi consiglio di leggere il modello faq: http://womble.decadentplace.org.uk/c++/template-faq.html –