2016-07-28 7 views
2

In einem Projekt habe ich eine Möglichkeit gefunden, DRY zu bleiben, da eine Menge Code mit Ausnahme einiger kleiner Teile für Template-Spezialisierungen einer Vorlage gleich bleiben kann. Hier ist ein kleines Arbeitsbeispiel, was ich zur Zeit mache ich das Templat-Klasse zu überprüfen bin mit:std :: ist gleichbedeutend für unspezialisierte Schablonentypen

template<typename T> 
class A{}; 

template<typename T> 
class B{}; 

template<template<class> class C> 
void do_stuff() 
{ 
    if(std::is_same<A<int>,C<int>>::value) 
    { 
    // Do Stuff for A 
    } else if(std::is_same<B<int>,C<int>>::value) 
    // Do Stuff for B 
    } 
} 

int main() 
{ 
    do_stuff<A>(); 
} 

Was würde Ich mag stattdessen zu tun ist

std::is_same<A,C>::value 

unter Verwendung die Schablone, um zu bestimmen Art. Gibt es irgendeine Funktion, die mir helfen könnte oder fehlt mir ein Muster, das in diesem Fall besser funktioniert?

Ich sehe, dass ich so etwas wie

template<template<class> class C, typename T> 
void do_stuff(); 

do_stuff<A,T>(); 

tun könnte, aber das scheint wie der falsche Weg für mich zu tun.

Antwort

5

Sie könnten eine is_same_template Eigenschaft schreiben, die für, wenn die beiden Template-Template-Parameter sind die gleichen teilweise spezialisiert ist:

template <template <typename...> class, template<typename...> class> 
struct is_same_template : std::false_type{}; 

template <template <typename...> class T> 
struct is_same_template<T,T> : std::true_type{}; 

Dann können Sie schreiben is_same_template<A,C>::value.

Beachten Sie, dass dies nicht für Vorlagen funktioniert, die nicht typisierte Vorlagenparameter haben, wie .

Einige Compiler wird kein Alias-Vorlage als äquivalent zu der Vorlage es Aliase, betrachten, so dass die folgenden in std::false_type führen würde:

template <typename T, typename Alloc> 
using MyVec = std::vector<T, Alloc>; 

is_same_template<std::vector, MyVec>; 

verlassen Dies wird als ein defect in the standard, aber man sollte nicht auf das Verhalten bis dieser Fix in allen gängigen Compilern implementiert ist.


Das heißt, müssen Sie vorsichtig sein, was Sie in diesen if Zweige setzen, da der Code, unabhängig davon, kompilieren muss, was die Vorlage mit instanziiert wird. In C++ 17 können Sie if constexpr verwenden, um dieses Problem zu lösen, aber vorerst müssen Sie den Versand kennzeichnen oder verschiedene Spezialisierungen haben, wenn die Zweige Code haben, der nur für A oder B gültig ist.

template <template <typename...> class> struct tag{}; 

template <template <typename> class T> 
void do_stuff() { 
    do_stuff(tag<T>{}); 
} 

void do_stuff(tag<A>) { 
    std::cout << "A"; 
} 

void do_stuff(tag<B>) { 
    std::cout << "B"; 
} 
+3

Es kann sich lohnen, unter Hinweis darauf, dass unter den aktuellen Sprachregeln, wenn ein Argument ist ein Alias-Vorlage wie 'Vorlage mit B A =;', 'is_same_template ' wird 'false_type'. Viele Menschen finden dies zunächst kontraintuitiv. – bogdan

+0

@bogdan Danke, ich habe eine Notiz hinzugefügt. – TartanLlama