2014-12-16 5 views
8

È possibile fare qualcosa come il seguente che compila senza specializzazione template?Metaprogramming con 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

Non è possibile combinare istruzioni per il preprocessore con l'istanza del modello del compilatore C++. –

+2

intendi 'A b', giusto? – qdii

+1

related: [specializzazione template class C++, senza dover reimplementare tutto] (http://stackoverflow.com/q/25486033/3953764) –

risposta

16

Sì. Rendere i modelli di funzione e poi conditionaly consentire loro utilizzando std::enable_if:

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

La soluzione da the other answer potrebbe non essere fattibile se la classe è grande e ha molte funzioni che devono prescindere dalla T. Ma puoi risolverlo ereditando da un'altra classe che viene utilizzata solo per questi metodi speciali. Quindi, puoi specializzare solo quella classe base.

In C++ 14, ci sono di tipo convenienti alias così la sintassi può diventare:

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

e C++ 17, ancora più breve:

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

Grandi cose! Molte grazie. – ZeroCool

+2

potresti aggiungere che in C++ 14 puoi scrivere 'std ::: enable_if_t' e in C++ 17 anche' std :: is_same_v' per sbarazzarti di 'typename ... :: type' e ':: value' verbosity. – TemplateRex

+1

@TemplateRex Fatto. – jrok

4

Sì, con il modello di specializzazione:

template <class T> 
class A; 

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

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

Esiste un modo senza riscrivere lo stesso codice due volte? – ZeroCool

+0

È possibile introdurre nuove dichiarazioni dei membri della classe con la specializzazione del modello? È qualcosa di nuovo per me. –

+1

@ZeroCool Forse in futuro è possibile: http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Static-If-I-Had-a-Hammer – 5gon12eder