【发布时间】:2021-01-03 03:08:41
【问题描述】:
template<typename T>
struct Test{};
template<typename T>
struct Test<T&&>{};
考虑上面的例子,标准规定类模板部分特化应该比它的主类模板更特化。
在类模板部分特化的参数列表中,适用以下限制:
专业化应该比主模板更专业化。
要确定哪个更专业,将对它们应用以下规则:
对于两个类模板部分特化,如果根据函数模板的排序规则,对两个函数模板进行以下重写,则第一个函数模板比第二个更特化:
p>
- 两个函数模板中的每一个都具有与对应的部分特化相同的模板参数。
- 每个函数模板都有一个函数参数,其类型是类模板特化,其中模板参数是来自函数模板的对应模板参数部分专业化。
对于初级类模板,重写后的函数模板是这样的:
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]) 的每个参数类型 Pi 与 P 的相应参数类型 Ai 进行比较A对应的参数类型列表。
可以在几种不同的上下文中推导出模板参数,但在每种情况下,都会将根据模板参数指定的类型(称为 P)与实际类型(称为 A)进行比较,并尝试查找模板参数值(类型参数的类型、非类型参数的值或模板参数的模板),在替换推导值(称为推导 A)后,使 P 兼容A.
这里,我们在每个函数类型中只有一个参数。所以比较Test<T>和Test<T&&>,反之亦然,temp.deduct.type#9中提到了这样的过程。
但我在这里争辩的是,标准中没有相关规则说明比较过程的细节。换句话说,为什么我们可以从T&&(T 将是T&&)推导出T,但反过来不行。如果我错过了有关细节的相关规则,请指出。如果标准中确实没有这样的细节描述,那么关于模板参数推演过程细节的相关技术在哪里可以找到呢?
【问题讨论】:
标签: c++ templates language-lawyer partial-ordering