【问题标题】:what's the original type for a member function template during partial ordering部分排序期间成员函数模板的原始类型是什么
【发布时间】: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&amp;, R&amp;),其转换后的类型为int operator*(UniqueA&amp;, UniqueB&amp;)#2 的原始类型毫无疑问。但是,我不知道#1(成员函数模板)的原始类型是什么。

该规则的结构似乎应该将上述规则中的强调部分视为生成转换模板的步骤。
所以,#1的原始类型是int operator*(B&lt;T&gt;&amp;, R&amp;)还是int operator*(R&amp;)。如果是后者,那就不符合常理了。由于int operator*(R&amp;)int operator*(T&amp;, R&amp;)的参数个数不匹配,如何比较(A和P)?

如何正确阅读生成转换模板的规则?如果强调的部分不被认为是转换的一个步骤,而是偏序过程中成员函数的一般规则,那么在转换过程之后放置这样的规则是否会误导?

【问题讨论】:

  • “原产地类型”不是标准中出现的术语;这是什么意思?
  • @ecatmur 我的意思是在部分排序期间#1 的原始类型。 “两组类型用于确定偏序。对于涉及的每个模板,都有原始函数类型和转换后的函数类型。”

标签: c++ templates language-lawyer


【解决方案1】:

是的,有点乱。正如您所观察到的,类非静态成员函数的“原始类型”缺少插入的 this 参数是没有意义的。

使其工作的唯一方法是将第 3 条中的后续段落应用于 [temp.deduct.partial] 另一侧的“原始”函数类型以及“转换”函数类型。对于目前第二段的第一句,您几乎可以这样阅读,将“每个”阅读为适用于转换后的函数类型和原始函数类型:

每个作为成员函数的函数模板M都被认为有一个新的X(M)类型的第一个参数[...]

但是,由于P2108 中对 CWG 2445 的决议,我们还有一句话:

如果某个函数模板被认为是 [...] 通过参数顺序颠倒的重写候选者,则函数参数在其转换后的模板中的顺序会颠倒。

所以我们很明显地不对称地应用了这种反转,给出了一个荒谬的结果。从好的方面来说,它应该如何阅读是相当清楚的。对函数类型的调整(this 插入和参数反转)应在唯一类型合成/替换之前应用,并同样适用于“原始”和转换后的函数类型。

据我所知,这个缺陷似乎没有报告给核心语言工作组;它没有出现在C++ Standard Core Language Active Issues 列表中。

【讨论】:

  • 同意你的看法。我认为第 3 段中的第二条规则应该放在 [temp.deduct.partial] 中,以使其适用于原始模板和转换后的模板。
  • 顺便说一句,reversed order of parameters 是什么?我不明白这是什么意思。你能举个例子解释一下是什么吗?
  • @jackX 这是 C++20 中的新功能,带有宇宙飞船;允许比较运算符在 RHS 类类型上查找成员 ==&lt;=&gt;,例如"hello" == "hello"s 可以致电 string::operator==(char const*)brevzin.github.io/c++/2019/07/28/comparisons-cpp20/…devblogs.microsoft.com/cppblog/…
  • 谢谢。我不熟悉 c++20 标准。我必须研究它。但是,在 CWG 2445 中,运算符函数 == 可以用作操作的候选函数!=,我只是不知道为什么。您能否提供有关最新标准的链接。
  • eel.is/c++draft/over.match.oper#3.4.3 发现了,虽然我没有进一步研究
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多