template<typename T>
struct Test{};
template<typename T>
struct Test<T&&>{};
考虑上面的例子,标准规定类模板部分特化应该比它的主类模板更特化。
在类模板部分特化的参数列表中,适用以下限制:
专业化应比主模板更专业化。
为了确定哪个更专业,将对其应用以下规则:
对于两个类模板部分特化,如果根据函数模板的排序规则,对两个函数模板进行以下重写,则第一个函数模板比第二个函数模板更特化:
- 两个函数模板中的每一个都具有与相应的偏特化相同的模板参数。
- 每个函数模板都有一个函数形参,其类型是类模板特化,其中模板实参是部分特化的 simple-template-id 的 template-argument-list 中的每个模板实参的函数模板的对应模板形参.
对于主类模板,重写后的函数模板是这样的:
template<typename T>
void ordering(Test<T>)
类模板偏特化的重写函数模板是这样的:
template<typename T>
void ordering(Test<T&&>)
根据“在部分排序期间推导模板参数”的规则:
用于确定排序的类型取决于完成部分排序的上下文:
- 在函数调用的上下文中,使用的类型是函数调用具有参数的那些函数参数类型。
- 在调用转换函数的上下文中,使用转换函数模板的返回类型。
- 在其他上下文中,使用函数模板的函数类型。
上面从参数模板中指定的每个类型和参数模板中的相应类型都用作 P 和 A 的类型。如果特定 P 不包含参与模板参数推导的模板参数,则该 P 不用于确定订购。
既不是function call
,也不call to a conversion function
是这个上下文。所以子弹3有效。这意味着,取void(Test<T>)
为 P 和取void(Test<T&&>)
为 A,反之亦然。
对于这对 P/A,就是temp.deduct.type#10中提到的情况,即
将 P 的相应参数类型列表 ([dcl.fct]) 的每个参数类型 P i与 A 的相应参数类型列表的相应参数类型 A i进行比较。
模板参数可以在几种不同的上下文中推导出来,但在每种情况下,都会将根据模板参数指定的类型(称为 P)与实际类型(称为 A)进行比较,并尝试查找模板参数值(类型参数的类型,非类型参数的值,或模板参数的模板)将使 P 在替换推导值(称为推导 A)后与 A 兼容。
在这里,我们在每个函数类型中只有一个参数。所以比较一下Test<T>
,Test<T&&>
反之亦然,这个过程在temp.deduct.type#9中提到。
但是我在这里争论的是,标准中没有相关规则说明比较过程的细节是什么。换句话说,为什么我们可以T
从T&&
(T would be T&&
) 推导出来,但反过来不行。如果我错过了有关细节的相关规则,请指出。如果标准中确实没有这样的细节描述,那么模板参数推演过程细节的相关技术在哪里可以找到呢?