2012-04-09 5 views
10

Als Teil einer Merkmalsklasse für ein größeres Programm habe ich versucht, eine statische Klassenvariable zu erstellen, die je nach dem Typ, mit dem die umschließende Klassenvorlage instanziiert wurde, einen anderen Wert haben kann.G ++ Compiler Fehler oder fehlerhafter Code? : "Vorlagedefinition von Nichtvorlage"

Ich habe den entsprechenden Code vereinfacht ein nackten Knochen Beispiel zu produzieren, was ich rede:

#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; 

mit GCC 4.6, das gibt einen Compiler-Fehler: template definition of non-template ‘std::string Foo<T, Enable>::message. Das Problem tritt wegen der letzten zwei Zeilen auf, wo ich gerade die statische Variable std::string Foo<T, Enable>::message definiere.

Ich bin verwirrt, warum das passiert. Der Compiler-Fehler verschwindet, wenn ich die letzten zwei Zeilen weglasse (aber das verursacht natürlich Linker-Fehler). Ist das ein Compilerfehler mit GCC?

+2

+1 für "ein bloßes Beispiel". http://sscce.org/. –

+0

Sie müssen

+0

@Vaughn einschließen, das ist nicht das Problem hier, aber ich habe das Code-Snippet aktualisiert. – Channel72

Antwort

10

Dies funktioniert nur, wenn Ihre Template-Parameter die partielle Spezialisierung entsprechen:

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; 

Diese in Abschnitt angegeben ist 14.5.4.3 des C++ 03-Standard. Die Idee ist, dass eine partielle Spezialisierung eine neue Vorlage ist und die Template-Parameter von extern definierten Membern den Template-Parametern der Klassendefinition entsprechen müssen, damit sie weiß, zu welcher Vorlage das Mitglied gehört.

In Ihrem Beispiel vermeidet die Regel die Definition des Nachrichtenmembers für Typen, die nicht ganzzahlig oder Gleitkommawerte sind.

+0

Warum funktioniert das nur in diesem Fall? – SirGuy

+0

Gibt es einen Grund, warum eine einzelne Definition hier nicht funktioniert? Ist das etwas vom C++ - Standard oder eine Eigenart in G ++? – Channel72

+0

@GuyGreer: Ich denke, da das statische Feld _message_ für die allgemeine Vorlage nicht deklariert ist (nur für einige Spezialisierungen). es ist unmöglich, etwas zu definieren, das nicht erklärt wird – user396672

Verwandte Themen