2016-06-30 13 views
0

ich den folgenden Code zu bekommen versuche zu kompilieren:C++ 11 enable_if Fehler - Template-Parameter Neudeklaration

template <class T, typename std::enable_if<!std::is_fundamental<T>::value, int >::type = 0 > 
class Calc 
{ 
    public: 
    int operator()(const T& v) const { 
     return v.getValue(); 
    } 
}; 

template <class T, typename std::enable_if<std::is_fundamental<T>::value, int >::type = 0 > 
class Calc : CalcBase <T> 
{ 
}; 

Auf Kompilation ich folgende Störung erhalte:

c.cpp:26: error: template parameter 'typename std::enable_if<(! std::is_fundamental::value), int>::type <anonymous>' 
c.cpp:36: error: redeclared here as 'typename std::enable_if<std::is_fundamental::value, int>::type <anonymous>' 

Die Absicht ist hier, die Version von Calc auszuwählen, die den Aufruf des Basisklassenfunktionsoperators überschreibt, wenn der übergebene Vorlagenparameter eine Klasse ist. Wenn der übergebene Parameter ein grundlegender Typ ist, wählen wir die Version von Calc, die die Basisklassenfunktionalität nicht überschreibt. Könnten Sie mir bitte helfen zu verstehen, wie ich das schaffen kann?

+0

Sie müssen mehr von Ihrem Code anzeigen. Es ist nicht klar, was die primäre Vorlage sein soll, was die Spezialisierung (en) ist –

+0

Es ist auch nicht klar, was dies bedeuten soll: 'typenname std :: enable_if :: value, int > :: type = 0' Wann und warum würde ein Typ gleich Null sein? Normalerweise würde ich denken, die Antwort ist, niemals. –

+0

@ChrisBeck In diesem Fall ist "type" ein Alias ​​für "int", und "int" kann ein nicht typisierter Vorlagenparameter sein, der einen Standardwert haben kann (z. B. 0). Das ist tatsächlich eine Möglichkeit, eine Funktion von der Teilnahme an der Überladungsauflösung zu entfernen, weil, wenn die Bedingung von 'std :: enable_if <>' falsch ist, es keinen 'type' Alias ​​gibt und SFINAE stattfindet. – user2296177

Antwort

4

Ich glaube nicht, dass Klassenvorlage-Deklarationen mit SFINAE arbeiten: Eine Klassenvorlage wird nicht wie eine Funktionsvorlage überladen. Sie deklarieren zwei primäre Klassenvorlagen mit demselben Namen, die nicht zulässig sind.

Sinnvollerweise ist SFINAE für Ihren Anwendungsfall nicht notwendig: Klassenvorlagen unterstützen Teilspezialisierung. Sie würden einfach einen voreingestellten bool-Parameter verwenden und die Klassenvorlage darauf spezialisieren, ob das Merkmal true oder false ist. Zum Beispiel:

template <class T, bool = std::is_fundamental<T>::value> 
class Calc 
{ 
    public: 
    int operator()(const T& v) const { 
     return v.getValue(); 
    } 
}; 

template <class T> 
class Calc<T, false> : CalcBase <T> 
{ 
}; 
+0

Das hat perfekt für mich funktioniert. Und tatsächlich eine sehr elegante Lösung. Vielen Dank für Ihre Hilfe. –