【问题标题】:Overloading conversion function templates重载转换函数模板
【发布时间】:2016-09-01 17:45:27
【问题描述】:

考虑以下几点:

struct X {
    template <class T> operator T();  // #1
    template <class T> operator T&(); // #2
};

int        a = X{}; // error: ambiguous
int&       b = X{}; // calls #2
int const& c = X{}; // calls #2

b 的情况很简单,#2 是唯一可行的候选人。什么规则表明#2 优先于#1 用于初始化int const&amp;,但两者对于int 的初始化有歧义?

【问题讨论】:

  • [over.match.conv][over.match.ref] 似乎是一个很好的起点。
  • @jaggedSpire 这些部分指示候选函数是什么。不是如何喜欢(或不喜欢)其中一个。
  • 这里的模板不是必须的,普通的operator intoperator int&amp;也是模棱两可的
  • "那些非显式转换函数......产生类型“对 cv2 T2 的左值引用”(在初始化左值引用时......)其中“cv1 T”是引用兼容的([dcl .init.ref]) 与“cv2 T2”,是候选函数“似乎向我表明了初始化左值类型的限制,这将取消int const&amp;的#1 的资格@
  • @TemplateRex 我知道这很明确。问题是为什么 a 模棱两可,而不是 c

标签: c++ language-lawyer overload-resolution conversion-operator


【解决方案1】:

当决定如何初始化一个给定初始化器的引用时,首先尝试直接绑定。 [dcl.init.ref]/(5.1.2):

如果引用是左值引用并且初始化表达式 […] 具有类类型(即,T2 是类类型),其中 T1T2 没有引用相关,并且可以是 转换为“cv3 T3”类型的左值,其中“cv1 T1”与“cv3 @987654328”引用兼容@”(通过枚举适用的转换函数 (13.3.1.6) 并通过重载决议 (13.3) 选择最佳转换函数来选择此转换),然后将引用绑定 [...] 到左值结果 的转换 […]。

支配这个过程的候选者选择的措辞(13.3.1.6,如上所述)不包括第一个转换函数:

考虑S及其基类的转换函数。 那些非显式的转换函数 没有隐藏在 S 中并且产生类型“对 cv2 T2 的左值引用”(在初始化对函数的左值引用或右值引用时)[...],其中“ cv1 T” 是引用兼容的 (8.6.3) 带有“cv2 T2”,是候选函数。对于直接初始化,[…]。

显然,这种排除是特定于引用初始化语义的,所以第一种情况仍然不明确。

【讨论】:

  • 但是您省略了考虑产生 cv2 T2 的转换函数的部分。其他候选函数发生了什么?
  • @Barry 不仅适用于“初始化函数的右值引用或左值引用”,还是我错过了你的意思?
  • @jaggedSpire 我想说的是,巴里让我困惑了一秒钟。如果转换函数返回纯右值,左值引用如何直接绑定到它?那会有点错过那部分的重点。
  • 是的,这就是我所缺少的。所以operator T() 是候选人的原因不是因为 13.3.1.6 说它是,而是因为我们回退到 8.6.3/5.2.2.1 并且 13.3.1.5 找到了它。对吗?
  • @Barry 候选人在什么情况下?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-04
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多