I know that a C++ compiler picks a template specialization in preference to the primary template:
template<class T, class Enable = void>
class A {}; // primary template
template<class T>
class A<T, std::enable_if_t<std::is_floating_point_v<T>, void>> {
}; // specialization for floating point types
However, I don't understand why the selection fails when a type other than void
is used as argument to enable_if
:
template<class T>
class A<T, std::enable_if_t<std::is_floating_point_v<T>, int>> {
}; // specialization for floating point types
The compiler would surely "see" class A<T, int>
.
So it certainly can't be SFINAE, nevertheless the primary template is preferred to the specialization.
This question arises from a context where a custom type detection machinery could be used instead of enable_if
, e.g. an SFINAE friendly type extractor like common_type
.
When you have
A<some_floating_point_type> some_name;
The template parameters are some_floating_point_type
and the implicit void
. When the compiler instantiates
template<class T>
class A<T, std::enable_if_t<std::is_floating_point_v<T>, int>> {
}; // specialization for floating point types
it would get A<some_floating_point_type, int>
, which does not match the A<some_floating_point_type, void>
type that some_name
has. Because of that, the specialization is ignored and you get the primary template. You can verify this by trying to create a A<some_floating_point_type, int>
and you'll get that the specialization was picked.
I find it helpful to think of a specialization as an alternate recipe. First the template arguments are deduced, and then if they match any of the specializations, then we switch to using that alternate recipe. If not, then the original recipe is used.
Specializations are irrelevant until the compiler knows which types it is going to use for the primary template.
When you write A<double>
, then the compiler looks only at the primary template and sees that you actually mean A<double,void>
.
And only then it is looking for specializations. Now, when your specialization is for A<double,int>
, then it is not suitable because you asked for A<double,void>
.
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