The question is simple: look at the code. Both static asserts pass. I would not expect the second one to pass. Is this a bug or normal behavior?
#include <array>
#include <type_traits>
template <template <class...> class Temp, class Specialization>
struct IsSpecialization : std::false_type {};
template <template <class...> class Temp, class... Ts>
struct IsSpecialization<Temp, Temp<Ts...>> : std::true_type {};
template <class...Args>
struct A {};
template <class...Args>
using AT = A<Args...>;
int main() {
static_assert(IsSpecialization<A, A<int>>{});
static_assert(!IsSpecialization<AT, AT<int>>{});
}
Temp is deduced twice when you try to match the partial specialization:
Temp against AT. This trivially deduces Temp to be AT.Temp<Ts...> against AT<int>. This deduces Temp to be A because AT<int> is equivalent to A<int>, and this deduction will never deduce an alias template (see [temp.alias]/2).The overall deduction succeeds - and the partial specialization is a match - iff the two deductions give Temp the same value, i.e., iff AT and A are considered to be equivalent. Whether they are is currently an open question.
Not an explanation (see the T.C.'s answer for it) but a workaround: modify the true version of IsSpecialization as follows
template <template <typename...> class Temp1,
template <typename...> class Temp2, typename... Ts>
struct IsSpecialization<Temp1, Temp2<Ts...>>
: public std::is_same<Temp1<Ts...>, Temp2<Ts...>>
{ };
T.C. explain that with your original code, AT is deduced as AT when seen as container and as A<Ts...> as type.
The trick is deduce AT and and A in different template-template argument, apply the same template types (Ts...) obtaining AT<Ts...> and A<Ts...>. But AT<Ts...> and A<Ts...> are the same type and std::is_same understand it.
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