In C++20, we have better NTTPs, which allows literal class types:
template <typename T>
struct A{};
template <A> // note: it is a placeholder for NTTP A<T>
struct B{};
But when I try to specialize a template for B
:
template <typename>
struct is_B{};
template <A x>
struct is_B<B<x>>{}; // error!!!
The compiler (GCC 10 or GCC 11(trunk)) dumps a bunch of errors:
prog.cc:11:15: error: class template argument deduction failed:
11 | struct is_B<B<x>>{};
| ^
prog.cc:11:15: error: no matching function for call to 'A(A<...auto...>)'
prog.cc:2:8: note: candidate: 'template<class T> A()-> A<T>'
2 | struct A{};
| ^
prog.cc:2:8: note: template argument deduction/substitution failed:
prog.cc:11:15: note: candidate expects 0 arguments, 1 provided
11 | struct is_B<B<x>>{};
| ^
prog.cc:2:8: note: candidate: 'template<class T> A(A<T>)-> A<T>'
2 | struct A{};
| ^
prog.cc:2:8: note: template argument deduction/substitution failed:
prog.cc:11:15: note: mismatched types 'A<T>' and 'A<...auto...>'
11 | struct is_B<B<x>>{};
| ^
prog.cc:11:16: error: template argument 1 is invalid
11 | struct is_B<B<x>>{};
| ^~
I found a solution, which is giving an explicit argument to A
:
template <typename T, A<T> x>
struct is_B<B<x>>{};
But it is redundant, and cannot solve the same error when A
used in using
:
template <A x>
using B_t = B<x>; // same error!!!
So is there another solution?