Twi*_*ice 6 c++ gcc templates template-argument-deduction c++20
在 C++20 中,我们有更好的 NTTP,它允许文字类类型:
template <typename T>
struct A{};
template <A> // note: it is a placeholder for NTTP A<T>
struct B{};
Run Code Online (Sandbox Code Playgroud)
但是当我尝试专门针对以下内容设计模板时B:
template <typename>
struct is_B{};
template <A x>
struct is_B<B<x>>{}; // error!!!
Run Code Online (Sandbox Code Playgroud)
编译器(GCC 10 或 GCC 11(trunk))会转储一堆错误:
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>>{};
| ^~
Run Code Online (Sandbox Code Playgroud)
我找到了一个解决方案,它给出了一个明确的论点A:
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>>{};
| ^~
Run Code Online (Sandbox Code Playgroud)
但它是多余的,并且在A使用时无法解决相同的错误using:
template <typename T, A<T> x>
struct is_B<B<x>>{};
Run Code Online (Sandbox Code Playgroud)
那么还有其他解决方案吗?
看来 GCC 不喜欢像 NTTP 那样的推导类类型的占位符,应该按照[temp.param]/6接受它(强调我的):
非类型模板参数应具有以下类型之一(可能是 cv 限定的):
- 结构类型(见下文),
- 包含占位符类型 ([dcl.spec.auto]) 的类型,或者
- 推导类类型的占位符( [dcl.type.class.deduct])。
已经有一个相关的错误报告(PR96331,请参阅@TC 提供的示例)。