Due to the template parameter with default argument in your primary template, when you write T<19>::size
, what you're really writing is T<19, int>::size
.
Now, there exist partial specializations for your template, thus, when figuring out which specialization a simple-template-id like T<19>
refers to, the compiler will try to find a matching partial specialization. To do so, it will look for a match between the actual template arguments 19, int
and the template arguments given in your partial specialization
template <size_t N>
struct T<N, typename std::enable_if<(N>10)>::type>
{ // ^-------------- this here -------------^
…
};
The first step is to figure out the arguments for the parameters of your partial specialization itself. In your case, the partial specialization has one parameter template <size_t N>
. This parameter is deduced by comparing the parameterized type T<N, typename std::enable_if<(N>10)>::type>
to the actual type T<19, int>
. Deduction yields 19
as argument for parameter N
. Substituting back into the specialization, we get
struct T<N, void>
as the deduced argument list for our specialization because std::enable_if<true>::type
is void
. The argument list 19, void
is not the same as 19, int
, therefore, the specialization is not a match and the primary template will be used.
So to make this work, you have to make sure that the type produced by your std::enable_if
argument matches the default argument of the last parameter of the primary template, i.e., either change the default argument to be void
template <size_t N, typename = void>
struct T
{
…
};
or make your std::enable_if
produce int
in the cases where you want the specialization to be used
template <size_t N>
struct T<N, std::enable_if_t<(N>10), int>>
{
…
};