If my understanding is correct, alias templates are actually templates and hence can be passed as arguments where a class template is expected. Which is what makes the following code valid -
template <template <bool, typename> T>
struct foo {};
foo<std::enable_if_t> x;
It is also possible to use partial specialization to match template classes. Which is why the following code prints "Version 2".
template <typename T>
struct foo {
static void print() {std::cout << "Version 1" << std::endl;}
};
template <template <typename> typename T, typename X>
struct foo<T<X>> {
static void print() {std::cout << "Version 2" << std::endl;}
};
template <typename T>
struct bar {
};
...
foo<bar<int>>::print();
Now my question is, why doesn't the following code print "Version 2", but instead prints "Version 1"
template <typename T>
struct foo {
static void print() {std::cout << "Version 1" << std::endl;}
};
template <template <bool, typename> typename T, bool X, typename Y>
struct foo<T<X, Y>> {
static void print() {std::cout << "Version 2" << std::endl;}
};
foo<std::enable_if_t<true, int>>::print();
Shouldn't the second partial specialization be a better match where T=std::enable_if_t, X=true, Y=int?
As expected, the following prints "Version 2"
In your example however, the type
std::enable_if_t<true, int>is equivalent tointand cannot match cannot matchT<X, Y>.cppreference explains it like this:
The alias
std::enable_if_tcan matchtemplate <bool, typename> typename, but once specialized it cannot be deconstructed.