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)
这也被上述所有编译器所接受。然而,最初的示例也很有趣,因为模板模板参数应该至少与模板参数一样专业,但直观上看起来并不如此。
按照规则,第二个例子是可以的。让我们引用他们的话:
#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)
现在,这两个模板满足完全相同的调用,因此每个模板至少与另一个模板一样专门化。
| 归档时间: |
|
| 查看次数: |
276 次 |
| 最近记录: |