2012-04-09 14 views
10

Come parte di una classe di caratteri per un programma più grande, ho tentato di creare una variabile di classe statica che poteva avere un valore diverso a seconda del tipo con cui il modello di classe allegato era istanziato.Errore del compilatore G ++ o codice errato? : "definizione modello di non-modello"

Ho semplificato il relativo codice per produrre un esempio ridotto all'osso di quello che sto parlando:

#include <iostream> 
#include <string> 
#include <type_traits> 

template <class T, class Enable = void> 
struct Foo; 

template <class T> 
struct Foo<T, 
    typename std::enable_if<std::is_integral<T>::value>::type 
> 
{ 
    static std::string message; 
}; 

template <class T> 
struct Foo<T, 
    typename std::enable_if<std::is_floating_point<T>::value>::type 
> 
{ 
    static std::string message; 
}; 

template <class T, class Enable> 
std::string Foo<T, Enable>::message; 

con GCC 4.6, questo dà un errore di compilazione: template definition of non-template ‘std::string Foo<T, Enable>::message. Il problema si verifica a causa delle ultime due righe, in cui sto solo definendo la variabile statica std::string Foo<T, Enable>::message.

Sono confuso perché questo sta accadendo. L'errore del compilatore scompare se ometto le ultime due righe (ma ovviamente ciò causa errori di linker.) Si tratta di un errore del compilatore con GCC?

+2

+1 per "un esempio di nudo". http://sscce.org/. –

+0

È necessario includere

+0

@Vaughn, non è questo il problema, ma ho aggiornato lo snippet di codice. – Channel72

risposta

10

Questo funziona solo quando i parametri di modello corrispondono alla specializzazione parziale:

template <class T> 
std::string Foo<T, 
    typename std::enable_if<std::is_integral<T>::value>::type 
>::message; 

template <class T> 
std::string Foo<T, 
    typename std::enable_if<std::is_floating_point<T>::value>::type 
>::message; 

Questo è riportato alla sezione 14.5.4.3 dello standard C++ 03. L'idea è che una specializzazione parziale è un nuovo modello e che i parametri del modello dei membri definiti esternamente devono corrispondere ai parametri del modello della definizione della classe in modo che sappia con quale modello il membro va.

Nel tuo esempio, la regola evita di definire il membro del messaggio per tipi che non sono interi o in virgola mobile.

+0

Perché funziona solo in quel caso? – SirGuy

+0

C'è qualche ragione per cui una singola definizione non funziona qui? Questo è qualcosa che è richiesto dallo standard C++ o una stranezza in G ++? – Channel72

+0

@GuyGreer: Suppongo che il campo statico _message_ non sia dichiarato per il modello generale (solo per alcune specializzazioni). è impossibile definire qualcosa che non è dichiarato – user396672

Problemi correlati