https://stackoverflow.com/a/22487113/4416169 in the following answer we can see the code in scrutiny:
#include <iostream>
#include <type_traits>
template <typename T, T N, typename = void >
struct X {
static const bool isZero = false;
};
template <typename T, T N>
struct X < T, N, typename std::enable_if<N == 0>::type > {
static const bool isZero = true;
};
int main(int argc, char* argv[]) {
std::cout << X <int, 0>::isZero << std::endl;
std::cout << X <int, 1>::isZero << std::endl;
return 0;
}
https://stackoverflow.com/a/35652391/4416169 here we can see how templates are chosen:
Choosing a template specialization happens in five steps:
- Take the primary template declaration.
- Fill in user-specified template arguments.
- Function templates only: Deduce additional template arguments.
- Use defaults for remaining template arguments.
- Use the partial ordering algorithm (C++14 14.5.6.2) to choose the best-matching specialization.
firstly, im aware that SFINAE will take care of excluding the struct with the std::enable_if<N==0> as it will not have the ::type defined (making it compile to error, but of course substitution failure is NOT an ERROR, just exclude the template from the final specialization options, so beautiful) when N != 0. Since N!=0 always results in the formerly defined template being chosen(the unspecialized one), I wonder why is it that N=0 chooses the latterly defined template(the specialized one) over the former. Thus following these steps we can further scrutinize(in the case of T=int and N=0):
- template<typename T, T N, typename = void>
- T is int, N is 0; template<int,0,(unnamed-type)>
- do nothing we are not a function.
- (unnamed-type) is void; template<int,0,void>
- this is explained here: https://stackoverflow.com/a/17008568/4416169
We know now that when we try to access X<int,0>::isZero there are two options, the one with the default template type set to void by default, and the one where that same template type is set to void but not by default but explicitly.
Does the compiler always prefer the template(out of all available template specializations) with the least arguments?
Moreover and expanding: would this mean that the template with the least actual arguments is chosen over the one with the same amount of explicit(explicit as in non-defaulted or obligatory) arguments but that has the remainder set to a default value?
To be even more clear:
template<typename T, T N, typename C = void>
struct defTempArgStruct {
static constexpr unsigned int value = 0;
};
template<typename T, T N>
struct defTempArgStruct<T,N>
{
static constexpr unsigned int value = 99;
};
int main()
{
std::cout << defTempArgStruct<int, 2>::value << std::endl;
}
why does that code choose the second specialized template(<typename T, T N>),displaying 99, over the first? And why does it choose the first, displaying 0, when the second, specialized, one changes to be:
template<typename T, T N>
struct defTempArgStruct<T,N,float>
{
static constexpr unsigned int value = 99;
};
very confusing.
PLEASE be eager to correct anything anywhere that im getting wrong!