【发布时间】:2021-03-19 23:33:41
【问题描述】:
考虑这个例子
struct A { };
template<class T> struct B {
template<class R> int operator*(R&); // #1
};
template<class T, class R> int operator*(T&, R&); // #2
部分排序将应用于#1 和#2 以选择最佳可行函数模板。
使用两组类型来确定偏序。对于涉及的每个模板,都有原始函数类型和转换函数类型。推演过程使用转换后的类型作为参数模板,将另一个模板的原始类型作为参数模板。对于偏序比较中涉及的每种类型,此过程执行两次:一次使用转换后的模板 1 作为参数模板,模板 2 作为参数模板,再次使用转换后的模板 2 作为参数模板和模板 1作为参数模板。
部分排序通过依次转换每个模板来选择两个函数模板中的哪一个比另一个更专业(参见下一段)
为了生成转换后的模板,对于每个类型、非类型或模板模板参数(包括其模板参数包),分别合成一个唯一的类型、值或类模板,并将其替换为该参数在模板的函数类型。 [ 注:为非类型模板参数合成的值类型中替换占位符的类型也是唯一合成类型。 — 尾注 ] 如果只有一个函数模板 M 是某个类 A 的非静态成员,则认为 M 在其函数参数列表中插入了新的第一个参数。给定 cv 作为 M 的 cv 限定符(如果有),如果 M 的可选 ref 限定符是 && 或者如果 M 没有 ref 限定符并且第一个参数是另一个模板具有右值引用类型。否则,新参数的类型为“对 cv A 的左值引用”。
所以,#2 的原始类型为int operator*(T&, R&),其转换后的类型为int operator*(UniqueA&, UniqueB&),#2 的原始类型毫无疑问。但是,我不知道#1(成员函数模板)的原始类型是什么。
该规则的结构似乎应该将上述规则中的强调部分视为生成转换模板的步骤。
所以,#1的原始类型是int operator*(B<T>&, R&)还是int operator*(R&)。如果是后者,那就不符合常理了。由于int operator*(R&)和int operator*(T&, R&)的参数个数不匹配,如何比较(A和P)?
如何正确阅读生成转换模板的规则?如果强调的部分不被认为是转换的一个步骤,而是偏序过程中成员函数的一般规则,那么在转换过程之后放置这样的规则是否会误导?
【问题讨论】:
-
“原产地类型”不是标准中出现的术语;这是什么意思?
-
@ecatmur 我的意思是在部分排序期间
#1的原始类型。 “两组类型用于确定偏序。对于涉及的每个模板,都有原始函数类型和转换后的函数类型。”
标签: c++ templates language-lawyer