I have been reading STL files to learn better ways to format my code, and to learn tricks to be more efficient. I have been reading the thread files and I can't figure out what some of the code does.
template<class _Fn,
class... _Args,
class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ // construct with _Fx(_Ax...)
...
}
std::enable_if_t
is
template<bool _Test,
class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;
template<class _Ty>
struct enable_if<true, _Ty>
{ // type is _Ty for _Test
using type = _Ty;
};
that code is all copyrighted in the thread and str1common STLs.
my only question is what does the class = enable_if_t<...>
do?
Look for S.F.I.N.A.E.: "Substitution Failure Is Not An Error".
See a possible implementation of std::enable_if
(std::enable_if_t
is only a helper using
, C++14 introduced, to access the type
in a simpler way)
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
Is made so iff (if and only if) the template boolean value (the first template parameter) is true
, std::enable_if<...>::type
is defined (with the type in the second template parameter; void
if unexpressed).
To make it simple, you have that, in your example
template<class _Fn,
class... _Args,
class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ // construct with _Fx(_Ax...)
...
}
enable_if_t
(that is typename std::enable_if<...>::type)
is available iff the first value (!std::is_same<typename std::decay<_Fn>::type, thread>::value
) is true
.
That is:
if !std::is_same<typename std::decay<_Fn>::type, thread>::value
is true
, the substitution class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>
is performed and the function is implemented
if !std::is_same<typename std::decay<_Fn>::type, thread>::value
is false
, the substitution class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>
fail, the function isn't implemented but this ins't an error (SFINAE).
Why the language permit this?
Because, by example, you can implement two version of the function
template<class _Fn,
class... _Args, // vvvv true case
class = enable_if_t<true == is_same<decay_t<_Fn>, thread>::value>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ /* do something */ }
template<class _Fn,
class... _Args, // vvvvv false case
class = enable_if_t<false == is_same<decay_t<_Fn>, thread>::value>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ /* do something else */ }
Suggestion: search for SFINAE and study it because is an important part of modern C++.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With