为什么会出现错误“没有匹配的函数可以调用 'A(A<...auto...>)'”?

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)

那么还有其他解决方案吗?

met*_*fox 3

看来 GCC 不喜欢像 NTTP 那样的推导类类型的占位符,应该按照[temp.param]/6接受它(强调我的):

非类型模板参数应具有以下类型之一(可能是 cv 限定的):

  • 结构类型(见下文),
  • 包含占位符类型 ([dcl.spec.auto]) 的类型,或者
  • 推导类类型的占位符( [dcl.type.class.deduct])。

已经有一个相关的错误报告(PR96331,请参阅@TC 提供的示例)。