2014-12-16 4 views
8

Ist es möglich, etwas wie das Folgende zu tun, die ohne Template-Spezialisierung kompiliert?Metaprogrammierung mit Std :: Is_Same

template <class T> 
class A { 
public: 
    #if std::is_same<T,int> 
    void has_int() {} 
    #elif std::is_same<T,char> 
    void has_char() {} 
    #endif 
}; 
A<int> a; a.has_int(); 
A<char> b; b.has_char(); 
+2

Sie nicht Präprozessoranweisungen mischen mit der Template-Instanziierung des C++ Compilers. –

+2

meinst du 'A b', richtig? – qdii

+1

verwandt: [C++ Klassenvorlage Spezialisierung, ohne alles neu zu implementieren] (http://stackoverflow.com/q/25486033/3953764) –

Antwort

16

Ja. Nehmen Sie die Funktionsschablonen und dann conditionaly ermöglichen sie std::enable_if mit:

#include <type_traits> 

template <class T> 
class A { 
public: 

    template<typename U = T> 
    typename std::enable_if<std::is_same<U,int>::value>::type 
    has_int() {} 

    template<typename U = T> 
    typename std::enable_if<std::is_same<U,char>::value>::type 
    has_char() {} 
}; 

int main() 
{ 
    A<int> a; 
    a.has_int(); // OK 
    // a.has_char(); // error 
} 

Die Lösung von the other answer nicht möglich sein könnte, wenn die Klasse groß und hat viele Funktionen bekommen, die unabhängig von T benötigen. Sie können dies jedoch lösen, indem Sie von einer anderen Klasse erben, die nur für diese speziellen Methoden verwendet wird. Dann können Sie nur diese Basisklasse spezialisieren.

In C++ 14 gibt es bequeme Art Aliase so die Syntax werden kann:

std::enable_if_t<std::is_same<U, int>::value> 

und C++ 17, noch kürzer:

std::enable_if_t<std::is_same_v<U, int>> 
+0

Tolles Zeug! Danke vielmals. – ZeroCool

+2

könnte man hinzufügen, dass man in C++ 14 'std ::: enable_if_t' und in C++ 17 sogar' std :: is_same_v' schreiben kann, um den 'typenamen ... :: type' und ':: value' Ausführlichkeit. – TemplateRex

+1

@TemplateRex Fertig. – jrok

4

Ja, mit Template-Spezialisierung:

template <class T> 
class A; 

template <> 
class A<int> 
{ 
    void had_int(){} 
}; 

template <> 
class A<char> 
{ 
    void had_char(){} 
}; 
+0

Gibt es eine Möglichkeit, ohne den gleichen Code zweimal neu schreiben? – ZeroCool

+0

Sie können neue Klassenmemberdeklarationen mit Template-Spezialisierung einführen? Das ist etwas Neues für mich. –

+1

@ZeroCool Vielleicht in der Zukunft können Sie: http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Static-If-I-Had-a-Hammer – 5gon12eder