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:
- Why we need Line 1 ?
- What is the meaning of syntax
<intas
T::*>templateparameter in Line
2 ?
Line 1: Choosing the partial specialization below if the test succeeds.
Line 2:
int T::*is only valid ifTis a class type, as it denotes a member pointer.As such, if it is valid,
void_<T>::typeyieldsvoid, having this partial specialization chosen for the instantiation with avalueoftrue.If
Tis 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 avalueoffalse.Everytime you see a
T::SOMETHING, ifSOMETHINGisn’t present, be it a type, a data member or a simple pointer definition, you got SFINAE going.