template<template<auto> class> struct A {};
template<int&> struct B {};
A<B> a;
int main() {}
所有三个编译器 MSVC、GCC 和 Clang 的最新版本都接受此代码(https://godbolt.org/z/b7Pv7Ybxv)。然而,auto
无法推断出引用类型,那么为什么允许这样做呢?或者编译器在查看标准内容时是否错误地接受了它?
我混淆了上面的参数和参数。我的目的是想问
template<template<int&> class> struct A {};
template<auto> struct B {};
A<B> a;
int main() {}
这也被上述所有编译器所接受。然而,原始示例也很有趣,因为模板模板参数应该是at least与模板参数一样专业,但直观上看起来并不那么专业。
按照规则,第二个例子是可以的。让我们引用他们的话:
#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 {};
并重写为两个函数模板:
// rewritten argument
template<auto V> void func(X<V>);
// rewritten parameter
template<int& V> void func(X<V>);
第二个似乎至少与第一个一样专门:第二个模板满足的每个函数调用也将由第一个模板满足。 (据我所知,第二个模板永远无法满足,因为你无法实例化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>);
现在,这两个模板满足完全相同的调用,因此每个模板至少与另一个模板一样专门化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)