具有引用非类型模板参数的模板是否应该与具有自动非类型模板参数的模板模板参数相匹配?

use*_*522 7 c++ template-templates language-lawyer auto non-type-template-parameter

template<template<auto> class> struct A {};
template<int&> struct B {};

A<B> a;

int main() {}
Run Code Online (Sandbox Code Playgroud)

所有三个编译器 MSVC、GCC 和 Clang 的最新版本都接受此代码 ( https://godbolt.org/z/b7Pv7Ybxv )。但是,auto无法推断出引用类型,那么为什么允许这样做呢?或者编译器在查看标准内容时是否错误地接受了它?


我混淆了上面的参数和参数。我的目的是想问

template<template<int&> class> struct A {};
template<auto> struct B {};

A<B> a;

int main() {}
Run Code Online (Sandbox Code Playgroud)

这也被上述所有编译器所接受。然而,最初的示例也很有趣,因为模板模板参数应该至少与模板参数一样专业,但直观上看起来并不如此。

n. *_* m. 0

按照规则,第二个例子是可以的。让我们引用他们的话:

#3当 P 至少与模板参数 A 一样专业时,模板参数与模板参数 P 匹配...

#4模板模板参数 P 至少与模板模板参数 A 一样专业化,如果根据以下对两个函数模板的重写,对应于 P 的函数模板至少与对应于 A 的函数模板一样专业化函数模板的部分排序规则。给定一个发明的类模板 X,其模板头为 A(包括默认参数和 require 子句,如果有的话):

  • 这两个函数模板分别具有与 P 或 A 相同的模板参数和 require 子句(如果有)。
  • 每个函数模板都有一个函数参数,其类型是 X 的特化,模板参数对应于相应函数模板中的模板参数,其中,对于函数模板的模板头中的每个模板参数 PP,有一个对应的模板参数 AA形成了。如果 PP 声明了一个模板参数包,那么 AA 就是包扩展 PP... ([temp.variadic]); 否则,AA 是 id-表达式 PP。

所以我们的模板参数是template<auto> class,我们的模板参数是template<int&> class。让我们发明一个类模板X

 template <auto> class X {};
Run Code Online (Sandbox Code Playgroud)

并重写为两个函数模板:

 // rewritten argument
 template<auto V> void func(X<V>);
 // rewritten parameter
 template<int& V> void func(X<V>);
Run Code Online (Sandbox Code Playgroud)

第二个似乎至少与第一个一样专门:第二个模板满足的每个函数调用也将由第一个模板满足。(据我所知,第二个模板永远不会被满足,因为你无法用X参数实例化int&;不确定这是否是 IFNDR;可能不是因为程序本身不包含func模板,它们是为了检查其他模板而发明的)。


不太明显的是,根据相同的规则,第一个示例也可以。Lety 发明了类模板X并再次重写:

 template <int&> class X {};

 // rewritten argument
 template<int& V> void func(X<V>);
 // rewritten parameter
 template<auto V> void func(X<V>);
Run Code Online (Sandbox Code Playgroud)

现在,这两个模板满足完全相同的调用,因此每个模板至少与另一个模板一样专门化。