I have a basic grasp of SFINAE, and I think I understand many of the examples of how std::enable_if exploits it to select function template specializations, but I'm having a hard time wrapping my head around how it works for class templates.
The following example is from cppreference.com's explanation of std::enable_if:
template<class T, class Enable = void>
class A {}; // primary template
template<class T>
class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
}; // specialization for floating point types
I'm having trouble understanding how using std::enable_if in this way helps select the specialization. (I don't doubt that it does.)
When the compiler sees a declaration like A<float> specialized;, it will see two possible template instantiations that fit:
- The "primary template"
A<T, Enable>whereTis the typefloatand Enable is the typevoid(because of the default value). - The specialization
A<T, void>whereTis the typefloatandvoidis the result of the expression with theenable_if.
Aren't those ambiguous? Both effectively result in A<T, void>, so why is the specialization chosen?
In a different case, like A<int> primary;, the options to the compiler seem to be:
- The primary,
A<T, Enable>, whereTis the typeintandEnableis the typevoid. - The specialization,
A<T, ?>, whereTis the typeintand the?represents where I'm completely lost. In this case, theenable_ifcondition is false, so it doesn't definetype, which leaves you withA<int, typename >. Isn't that a syntax error? Even in the face of SFINAE?