2013-02-08 20 views
5

Ho difficoltà a definire e specializzare una funzione membro update() di una classe interna Outer<T1>::Inner che è basata su un argomento non di tipo (enum).Definizione di un modello di funzione membro della classe interna con un argomento enum (non di tipo)

#include <cstdlib> 

template<typename T1> 
struct Outer 
{ 
    struct Inner 
    { 
     enum Type{ A , B , C }; 

     template<Type T2> 
     void update(); 
    }; 
}; 

// Definition 
template<typename T1> 
template<Outer<T1>::Inner::Type T2> 
void Outer<T1>::Inner::update() 
{ 
} 

// Specialization 
template<typename T1> 
template<Outer<T1>::Inner::A > 
void Outer<T1>::Inner::update() 
{ 
} 

int main() 
{ 
    return EXIT_SUCCESS; 
} 

sto ottenendo il seguente messaggio di errore nel GCC 4.5.3

prog.cpp:17:28: error: ‘Outer::Inner::Type’ is not a type 
prog.cpp:18:6: error: prototype for ‘void Outer<T1>::Inner::update()’ does not match any in class ‘Outer<T1>::Inner’ 
prog.cpp:11:15: error: candidate is: template<class T1> template<Outer<T1>::Inner::Type T2> void Outer<T1>::Inner::update() 
prog.cpp:24:28: error: ‘Outer::Inner::A’ is not a type 
prog.cpp:25:6: error: prototype for ‘void Outer<T1>::Inner::update()’ does not match any in class ‘Outer<T1>::Inner’ 
prog.cpp:11:15: error: candidate is: template<class T1> template<Outer<T1>::Inner::Type T2> void Outer<T1>::Inner::update() 

BTW, a differenza di GCC, Visual Studio 2008 è in grado di compilare il seguente

template<typename T1> 
struct Outer 
{ 
    struct Inner 
    { 
     enum Type{ A , B , C }; 

     template<Type T2> 
     struct Deep; 
    }; 
}; 

template<typename T1> 
template<typename Outer<T1>::Inner::Type T2> 
struct Outer<T1>::Inner::Deep 
{ 
}; 
+0

Devo ammettere questo generato uno dei messaggi di errore più umoristici di VC2012 che ho visto in un istante: 'errore C2244: 'Esterno :: Interno :: aggiornamento': impossibile associare la definizione di funzione a una dichiarazione esistente, definizione 'void Outer :: Inner :: update (void)', dichiarazioni esistenti: 'void Esterno :: Inner :: update (void)' 'La notevole differenza tra le dichiarazioni esistenti e quelle desiderate è così ovvia, non è = P – WhozCraig

+1

Stavo per segnalare che Visual Studio 2008 non approva. C'è una soluzione? In realtà sto codificando in VS. Uso GCC per i controlli di conformità sanitaria. – Olumide

+0

@Olumide sarà sufficiente un controllo di runtime per ciò che stai facendo? Molto probabilmente il compilatore ottimizzerà il controllo e il codice morto perché sa che sarà sempre vero o falso. –

risposta

4

Prima di tutto, ti manca uno typename prima dello Outer<T1>::Inner::Type. Devi averlo, anche in un elenco di tipi template, perché Type è un tipo dipendente.

In secondo luogo, la sintassi di specializzazione è sbagliato (il tipo va in <> dopo il nome della funzione, prima le parentesi, non nella template<>), ma anche se fosse corretta, non sarebbe legale. Devi specializzare il modello esterno Outer prima di specializzarti completamente su update, secondo una sfortunata regola riguardante la specializzazione esplicita dei modelli.

+0

Doh! ... (Grazie) – Olumide

+2

Per il beneficio degli non illuminati: come sarebbe "specializzare il modello esterno" in questo caso? – us2012

+1

@ us2012 sarebbe semplicemente 'modello <> modello <> vuoto Esterno :: Interno :: aggiornamento :: Interno :: A>()' o qualsiasi altra cosa. Il punto è che anche "Outer" deve essere specializzato. –