Cherchez S.F.I.N.A.E. : "Substitution Failure Is Not An Error".
Voyez une implémentation possible de std::enable_if
(std::enable_if_t
n'est qu'une aide using
, introduite en C++14, pour accéder au type
de manière plus simple)
template
struct enable_if {};
template
struct enable_if { typedef T type; };
Est faite ainsi iff (if and only if) la valeur booléenne du template (le premier paramètre de template) est true
, std::enable_if<...>::type
est défini (avec le type dans le deuxième paramètre de template ; void
si non exprimé).
Pour simplifier, vous avez que, dans votre exemple
template, thread>::value>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ // construct with _Fx(_Ax...)
...
}
enable_if_t
(qui est typename std::enable_if<...>::type)
est disponible si et seulement si la première valeur (!std::is_same::type, thread>::value
) est true
.
C'est-à-dire:
-
si !std::is_same::type, thread>::value
est true
, la substitution class = enable_if_t, thread>::value>>
est effectuée et la fonction est implémentée
-
si !std::is_same::type, thread>::value
est false
, la substitution class = enable_if_t, thread>::value>>
échoue, la fonction n'est pas implémentée mais ce n'est pas une erreur (SFINAE).
Pourquoi le langage permet-il cela?
Parce que, par exemple, vous pouvez implémenter deux versions de la fonction
template, thread>::value>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ /* faire quelque chose */ }
template, thread>::value>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ /* faire quelque chose d'autre */ }
Suggestion : cherchez SFINAE et étudiez-le car c'est une partie importante du C++ moderne.