template<typename T>
struct Test{};
template<typename T>
struct Test<T&&>{};
考虑上面的例子,标准规定类模板偏特化应比其主类模板更加专业化。
在类模板偏特化的参数列表中,应遵守以下限制:
该特化应比主模板更加专业化。
为了确定哪个更加专业化,将对它们应用以下规则:
对于两个类模板的部分特化,如果给出以下重写到两个函数模板,则第一个函数模板根据函数模板排序规则比第二个更加专业化:
每个两个函数模板都有与对应的部分特化相同的模板参数。
每个函数模板都具有单个函数参数,其类型是一个类模板特化,其中模板参数是从函数模板的每个模板参数中获取的,这些模板参数包含在部分特化的simple-template-id的模板参数列表中。
对于主类模板,重写的函数模板将如下所示:
template<typename T>
void ordering(Test<T>)
而类模板部分特化的重写函数模板应该像这样:
template<typename T>
void ordering(Test<T&&>)
根据“在部分排序期间推导模板参数”的规则:
用于确定排序的类型取决于执行部分排序的上下文环境:
- 在函数调用的上下文环境中,使用函数参数类型作为类型,该函数调用具有参数。 - 在调用转换函数的上下文环境中,使用转换函数模板的返回类型。 - 在其他上下文中使用函数模板的函数类型。
从参数模板中提名的每个类型和来自参数模板的相应类型都用作P和A的类型。如果特定的P不包含参与模板参数推导的模板参数,则不使用该P来确定排序。
既不是“函数调用”也不是“调用转换函数”的上下文环境。因此,第3个项目适用。这意味着以
void(Test<T>)
作为P,以void(Test<T&&>)
作为A,反之亦然。对于这个P/A对,它是在temp.deduct.type#10中提到的情况,也就是说,
每个参数类型Pi在相应的参数类型列表([dcl.fct])中与相应参数类型列表A的Ai进行比较。
在几种不同的上下文中可以推导模板参数,但在每种情况下,将以模板参数为基础指定的类型(称之为P)与实际类型(称之为A)进行比较,并尝试找到模板参数值(类型参数的类型,非类型参数的值或模板参数的模板),使得在替换推导出的值(称之为推导出的A)后,P与A兼容。
在这里,每个函数类型只有一个参数。因此将
Test<T>
与Test<T&&>
进行比较,反之亦然,在temp.deduct.type#9中提到了这个过程。但是我在这里认为标准中没有相关规则说明比较过程的细节。换句话说,为什么我们可以从
T&&
推导出T
(T将成为T&&
),但反过来不行。如果我错过了相关规则的细节,请指出。如果标准确实没有这样的详细描述,那么在哪里可以找到有关模板参数推导过程细节的相关技术?
P
是void(Test<T&&>)
或者void(Test<T>)
,该规则并没有说我们可以删除模板参数列表中出现的引用。该规则的含义实际上是说,如果P
是Test<T>&&
,那么在部分排序之前,它应该转换为Test<T>
。 - xmh0511