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