2016-06-07 10 views
4

lassen Sie uns sagen, ich habe eine Aufzählung:Verwenden von C++ std :: enable_if mit einer normalen Funktion?

typedef enum { 
    Val1, 
    Val2, 
    Val3, 
    Val4 
} vals; 

und eine Funktion check(vals x), die einen boolean zurück, der angibt, ob die val in einer bestimmten Untergruppe von Werten in vals ist.

bool check(vals x) { 
    switch(x) { 
    case Val1: 
    case Val3: 
    return true; 
    } 
    return false; 
} 

Ich mag diese Funktion als Bedingung für die Verwendung für die enable_if (die Funktion, wie Sie sehen können, ist es nicht eine Funktion auf der Laufzeit abhängig), die Benutzer nur die Werte mit der Klassenvorlage verwenden zu lassen .

PS: Ich brauche die Vorlage, um Spezialisierungen für eine Methode der Klasse, abhängig von der Vorlage Wert.

+1

Haben Sie versucht, 'check'' constexpr' zu erstellen? – KABoissonneault

+0

@KABoissonneault Ich sollte C++ 11 Funktionen häufiger betrachten. Vielen Dank! – NoImaginationGuy

+0

@osnapitzkindle: Ich glaube nicht, dass ein C++ 11-Compiler den 'Schalter' in einer 'constexpr'-Funktion akzeptiert, aber Sie können einen booleschen Ausdruck verwenden. –

Antwort

4

Sie brauchen weder eine Funktion noch enable_if, das zu tun.
Hier ist ein Beispiel:

enum class vals { 
    Val1, 
    Val2, 
    Val3, 
    Val4 
}; 

template<vals v, bool = (v == vals::Val1 || v == vals::Val3)> 
class MyClass; 

template<vals v> 
class MyClass<v, true> { }; 

int main() { 
    MyClass<vals::Val1> ok; 
    // MyClass<vals::Val2> ko; 
} 

Diese Lösung hat tatsächlich ein Problem: MyClass<vals::Val2, true> ok; ist eine gültige Aussage.
Wie auch immer, wenn es gut passt hängt meistens vom wirklichen Problem ab.

Wenn Sie enable_if verwenden möchten, können Sie dies tun:

#include<type_traits> 

enum class vals { 
    Val1, 
    Val2, 
    Val3, 
    Val4 
}; 

template<vals v, std::enable_if_t<(v == vals::Val1 || v == vals::Val3)>* = nullptr> 
class MyClass { }; 

int main() { 
    MyClass<vals::Val1> ok; 
    // MyClass<vals::Val2> ko; 
} 

Eine andere Lösung wäre mit einem static_assert:

enum class vals { 
    Val1, 
    Val2, 
    Val3, 
    Val4 
}; 

template<vals v> 
class MyClass { 
    static_assert((v == vals::Val1 || v == vals::Val3), "!"); 
}; 

int main() { 
    MyClass<vals::Val1> ok; 
    // MyClass<vals::Val2> ko; 
} 

Und so weiter, gibt es eine Reihe von Alternativen, die nicht der Fall ist erfordern eine constexpr Ed-Funktion.

Ansonsten die Funktion constexpr wie von @ n.m. und das ist alles.

6

In C++ 14, nur die Funktion constexpr deklarieren und die Implementierung beibehalten, wie es ist.

In C + 11 Sie müssen es auf eine einzige return-Anweisung ändern:

constexpr bool check(vals x) { 
    return x == Val1 || x == Val3; 
} 
0

Danke für die Antwort Jungs. Ich fand eine andere Lösung, die für mein Problem noch besser sein könnte. Da ich für alle unterstützten Werte eine spezielle Methode implementieren muss, kann ich sogar eine Assertion in die unspezialisierte Methode schreiben.

template<vals v> 
MyClass<v>::method() { 
    assert(check(v) && "Unsupported value!"); 
} 

template<> 
MyClass<Val1>::method() { 
    // do it! 
} 
Verwandte Themen