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.
Es ist ein voreingestellter Template-Parameter ohne Namen. Der wichtigste "andere Anwendungsfall" liegt in Konstruktorschablonen, da Konstruktoren keinen Rückgabetyp haben. –