Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How come? aliases not detected in trait

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>>{});
}
like image 482
Germán Diago Avatar asked Jan 28 '23 21:01

Germán Diago


2 Answers

Temp is deduced twice when you try to match the partial specialization:

  • By matching Temp against AT. This trivially deduces Temp to be AT.
  • By matching 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.

like image 160
T.C. Avatar answered Jan 31 '23 11:01

T.C.


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.

like image 34
max66 Avatar answered Jan 31 '23 11:01

max66