2016-04-14 8 views
1

Ich verstehe nicht ganz unter Code, gibt es zwei Parameter für die Vorlage, die zweite hat class = xxxx, das scheint mir seltsam. Kannst du es mir erklären, wie soll ich es verstehen? und neben std::enable_if, gibt es noch einen anderen Anwendungsfall für diese C++ Funktion?Vorlage Parameter mit Standardwert für Klasse

template < class T, 
class = typename std::enable_if<std::is_integral<T>::value>::type> 
bool is_even (T i) {return !bool(i%2);} 
+0

Es ist ein voreingestellter Template-Parameter ohne Namen. Der wichtigste "andere Anwendungsfall" liegt in Konstruktorschablonen, da Konstruktoren keinen Rückgabetyp haben. –

Antwort

2

Ein Wort: SFINAE.

Substitutionsfehler ist kein Fehler.

Suchen Sie nach diesem Wort mit Google und eine ganz neue Welt wird sich für Sie öffnen.

Lassen Sie die Bedeutung Ihres Codes sehen.

std::is_integral<typename T>::value 

Es ist ein boolescher Wert, abhängig vom Typ T, mit dem Wert true wenn T ein Integral-Typ ist, false anders.

std::enable_if<bool B, typename T = void>::type 

Es ist die Art T, wenn B == true, nichts sonst.

Also, in Ihrem Code

template < class T, 
class = typename std::enable_if<std::is_integral<T>::value>::type> 

wenn T einen integralen Typ ist, wird das zweite (unbenannt) Template-Argument mit einem Typ ersetzt (der Standard: void, aber in diesem Fall, die genaue Art ist irrelevant) und die Funktion ist aktiviert. Im Gegensatz dazu, wenn T ist kein integraler Typ, gibt es den Fehler in der Ersetzung der zweiten Vorlage Argument und diese Version der is_even() Funktion ist nicht aktiviert (für Typ T) und, das ist der wichtige Punkt, es ist kein Fehler (eine andere Version von is_even() kann aktiviert werden).

Interessanter kann sehen, wie eine alternative Version von is_even(), für nicht integrale Typen zu implementieren. Sie denken, dass Sie eine andere Version implementieren können, die std::is_integral

template < class T, 
class = typename std::enable_if<false == std::is_integral<T>::value>::type> 

negieren, aber diese funktionieren nicht (ist ein Fehler und nicht kompilieren), weil Sie zwei is_even() Templat-Funktion, die (aus den Vorlagen unterscheidet Argumente zeigen of view) nur für ein Standardargument.

Eine Lösung kann SFINAE auf den Rückgabewert

#include <type_traits> 
#include <iostream> 

template <typename T> 
typename std::enable_if<true == std::is_integral<T>::value, bool>::type 
is_even (T const & i) 
{ return ! (i%2); } 

template <typename T> 
typename std::enable_if<false == std::is_integral<T>::value, bool>::type 
is_even (T const &) 
{ return false; } 


int main() 
{ 
    std::cout << "-- is 7 even ?  " << is_even(7) << '\n'; 
    std::cout << "-- is 8UL even ? " << is_even(8LL) << '\n'; 
    std::cout << "-- is \"abc\" even ? " << is_even("abc") << '\n'; 

    return 0; 
} 

Auf diese Weise können Sie eine Version von is_even() für Integraltyp und eine zweite Version (das Rückholsogar false) für nicht integrale Typen aktiviert haben anwenden.

S.: Entschuldigung für mein schlechtes Englisch.