2015-10-24 4 views
5

Ich möchte prüfen, ob zwei Typen gleich sind, aber unabhängig von ihren Template-Parametern. Etwas wie folgt aus:Wie überprüft man, ob zwei Typen aus der gleichen Template-Klasse stammen

template<class T> 
class A {}; 
class B {}; 

int main() { 
    cout << std::is_same_template<A<int>, A<string>>::value << endl; // true 
    cout << std::is_same_template<A<int>, B>::value << endl; // false 
} 

Ich bin mir bewusst, std::is_same zu überprüfen, ob zwei Typen exacty entsprechen.

Ein Grund, warum ich das brauchen: Ich habe eine Templat-Methode, die mit jeder Art bezeichnet werden kann, aber ich möchte, dass verbieten, ist mit Art A (das Templat-) genannt wird, möglicherweise durch einen static_assert verwenden. Wurde A nicht als Templat, ich glaube, es leicht std::is_same mit getan werden könnte, aber jetzt, ich habe ein Problem ...

EDIT: ich manuell A für ein paar gemeinsamen Ts ausschließen kann, indem ich für eine Suche so, wie es für alle T zu tun:

static_assert(!std::is_same<parameter_type, A<int>>::value, "Cannot use this function with type A<T>"); 
static_assert(!std::is_same<parameter_type, A<double>>::value, "Cannot use this function with type A<T>"); 
static_assert(!std::is_same<parameter_type, A<bool>>::value, "Cannot use this function with type A<T>"); 
+0

Zwei Arten sind nicht gleich, wenn ihre Template-Parameter unterschiedlich sind. Somit sind "A " und "A " weit davon entfernt, vom gleichen Typ zu sein. – skypjack

+2

Nun, ich bin mir dessen bewusst, deshalb kann ich 'std :: is_same' nicht verwenden. Was ich frage ist, wenn es eine Möglichkeit gibt, weniger streng zu vergleichen, A und A Vergleich gleich und A und B nicht zu machen? – jureslak

+0

Sie können den umgekehrten Ansatz mittels Template-Spezialisierung verwenden, akzeptieren Sie also nur die erlaubten Klassen und definieren Sie ansonsten eine leere/zerbrochene/werfende/was auch immer Funktion. – skypjack

Antwort

4

okay, wie wäre es damit:

#include <iostream> 

template<class T> 
struct A {}; 
struct B {}; 

template <typename T> 
struct should_reject { static constexpr bool value = false; }; 

template <typename T> 
struct should_reject<A<T>> { static constexpr bool value = true; }; 

template <typename T> 
void rejectA(T t) 
{ 
    std::cout << should_reject<T>::value << std::endl; 
} 

int main() { 
    rejectA(B());   // false 
    rejectA(1);   // false 
    rejectA(1.0);   // false 
    rejectA(A<B>());  // true 
    rejectA(A<int>()); // true 
    rejectA(A<double>()); // true 
} 
+0

Ich möchte diese beiden in deinem Beispiel vergleichen, aber du hast mir ein paar Ideen gegeben. Könnte ich zwicken, um die Typen zu verwerfen, die ein cetain typdef definiert haben? Oder vielleicht sogar ein Laufzeitwert ... (und der Downvote gehört mir nicht) – jureslak

+0

Oh, ich habe deine Frage völlig falsch verstanden. Das tut mir leid. –

+0

Ich habe meine Antwort bearbeitet. –

3

ich mit einer einfacheren Art und Weise habe kommen als @ NikitaKakuev Antwort, verwendet zur Zeit auf einem project of mine.

Das einzige aktuelle Problem ist mit Vorlagen, die Typen und Typnamen mischen, dh. std::array<int, 10>.
Um diese Einschränkung zu überwinden, ist Spezialisierung erforderlich.

Verbrauch:

bool b = is_same_template<std::string, std::wstring>; //true 
//both are typedefs of std::basic_string 

EDIT: Wie unten durch @Helix im Kommentar gebeten, Spezialisierung für std::array (oder jede andere Vorlage mit derselben Signatur):

template< 
    template<typename, std::size_t> class T, //typename T in C++17 
    typename TA, std::size_t NA, 
    typename TB, std::size_t NB 
> 
constexpr bool is_same_template< 
    T<TA, NA>, 
    T<TB, NB> 
>{true}; 
+0

Hey, ich habe mich gefragt, ob du deine Antwort aktualisieren kannst, um ein Beispiel für diese Spezialisierung einzuschließen? – FrogTheFrog

+1

@Helix du gehst. – bit2shift

Verwandte Themen