While reading this question , I came across @Johannes's answer.
template<typename> struct void_ { typedef void type; };
template<typename T, typename = void> // Line 1
struct is_class { static bool const value = false; };
template<typename T>
struct is_class<T, typename void_<int T::*>::type> { // Line 2
static bool const value = true;
};
This construct finds if the given type is a class or not. What puzzles me is the new kind of syntax for writing this small meta program. Can anyone explain in detail:
<int
T::*>
as template
parameter in Line
2 ?Line 1: Choosing the partial specialization below if the test succeeds.
Line 2: int T::*
is only valid if T
is a class type, as it denotes a member pointer.
As such, if it is valid, void_<T>::type
yields void
, having this partial specialization chosen for the instantiation with a value
of true
.
If T
is not of class type, then this partial specialization is out of the picture thanks to SFINAE and it defaults back to the general template with a value
of false
.
Everytime you see a T::SOMETHING
, if SOMETHING
isn't present, be it a type, a data member or a simple pointer definition, you got SFINAE going.
for example:
class foo {};
if (is_class<foo>::value) // is a class
line_2 called
else // if not
line 1 called
because of there is a partial specialization so line 1 is what you have to have, otherwise you will get an error if you pass a type which is not a class (such as char *, long, int ...)
means a pointer points to a member of a class, can be both a function or a data field, and in this case it means anyone who has a member or can work with a member pointer, this is only works for classes, structs, or unions in c++, so the result of that, you will know the parameter is or not a class.
btw, google some keywords like: c++ template, partial specialization, and type traits, or boost type traits
hope this is useful for you :)
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