2016-11-04 2 views
1

Ich habe eine Funktionsvorlage und ich möchte die Reihe der Typen, für die es instanziiert werden kann, einschränken.Definieren eines benutzerdefinierten Prädikats als eine Kombination aus Std :: Is_Same

Ich schrieb etwas wie folgt aus:

template <typename T> 
void DoSomething(/* ... Some parameters involving T ... */) 
{ 
    // Check at compile-time that T is allowed 
    static_assert(
     std::is_same<T, int>::value 
     || std::is_same<T, float>::value 
     || std::is_same<T, double>::value 
     ... 
     || std::is_same<T, /* other type */>::value, 
     "Type not allowed"); 
} 

ich die gleiche Prüfung für andere Funktionsschablonen zu wiederholen.

Eine naheliegende Lösung wäre Kopieren und Einfügen der oben genannten static_assert Überprüfung, aber das wäre schlecht für die Code-Wartbarkeit.

Eine bessere Lösung könnte sein, die static_assert Prüfung in eine Ad-hoc- Helfer-Funktion zu wickeln, und rufen Sie es in jeder Funktion Vorlagen, in denen ich die Typüberprüfung benötigen.

Aber was glaube, ich würde mehr elegant sein definiert eine benutzerdefinierte Kombination von std::is_same Anrufe, dass ich so verwenden könnte:

static_assert(IsTypeAllowed<T>::value, "Type not allowed"); 

Wie kann ich meine Gewohnheit definieren IsTypeAllowed<T> als eine Kombination von std::is_same Anrufe || 'Ed zusammen?

+2

Wenn Sie nur ganzzahlige Typen ausschließen möchten, können Sie mit [ ' std :: is_integral '] (http://en.cppreference.com/w/cpp/types/is_integral). –

+0

@ πάνταῥεῖ: Danke, ich kannte 'std :: is_integral', aber es ist eine bestimmte Teilmenge Auswahl (es gibt auch andere benutzerdefinierte Typen). –

Antwort

1

In C++ 1z Sie Ihren eigenen Zug mit std::disjunction rollen kann:

template<typename T, typename... Others> 
struct is_any : std::disjunction<std::is_same<T, Others>...> 
{ 
}; 

Dann ist es so einfach wie

static_assert(!is_any<int,char,bool>::value); 
//static_assert(!is_any<int,char,bool,int>::value); //error 

demo

Sie bilden kann weiter das bekommen Genaue Schnittstelle, nach der Sie gefragt haben:

template<typename T> 
using IsTypeAllowed = std::bool_constant<!is_any<T, char, bool, int>::value>; 

Wenn Sie diese in C++ 14 benötigen, müssen Sie schauen Vater nicht als die mögliche Implementierung von cppreference bereitgestellt:

template<class...> struct disjunction : std::false_type { }; 
template<class B1> struct disjunction<B1> : B1 { }; 
template<class B1, class... Bn> 
struct disjunction<B1, Bn...> 
    : std::conditional_t<B1::value != false, B1, disjunction<Bn...>> { }; 
Verwandte Themen