【问题标题】:Overload resolution and user defined conversion重载分辨率和用户定义的转换
【发布时间】:2016-04-02 02:37:48
【问题描述】:

考虑一下简单的代码:

struct A;
struct B {
  B(){}
  B(A const&){ }
};

struct A {
  operator int() const {return 0;};
};
void func(B){}
void func(char){}

int main()
{
func(A()); //ambiguous call oO
}

首先,我不确定我是否正确理解了所有内容,因此请在您发现我的错误时纠正我。

我的理解是应该选择void func(B),因为func 的参数是A,这是类类型,因此所需的转换类型是“用户定义的转换序列”

现在来自 IBM C++ 参考:

用户定义的转换序列包括以下内容:

  • 标准转换序列
  • 用户定义的转换
  • 第二个标准转换序列

现在存在两个用户定义的转换 B::B(const A&)A::operator int (const A&);

所以顺序是

-> A() -> B::B(const A&) -> Standard conversion (identity conversion)

-> A() -> A::operator int (const A&) -> Standard conversion (integral conversion)

由于积分转换比身份转换差,我认为void func(B) 会调用,但调用仍然模棱两可。

所以请帮助我在哪一点上我错了,为什么这个电话是模棱两可的。非常感谢:)

【问题讨论】:

  • 我认为将B 喂给func(B) 是身份,A->B::B->func(B) 可能不是;不过应该检查标准。

标签: c++ overload-resolution


【解决方案1】:

这里的两个转换序列A -> BA -> int 都是用户定义的,因为它们通过您定义的函数进行操作。

自定义转换序列排序规则见13.3.3.2(N3797):

用户定义的转换序列U1 是比另一个用户定义的转换序列U2 更好的转换序列,如果它们包含相同的用户定义的转换函数或构造函数,或者它们在聚合初始化中初始化相同的类并在无论哪种情况,U1 的第二个标准转换序列都优于U2 的第二个标准转换序列

这两个转换序列不包含相同的用户定义转换函数,并且它们在聚合初始化中不初始化同一个类(因为一个初始化int)。

因此,一个序列排名高于另一个序列是不正确的,因此这段代码是模棱两可的。

【讨论】:

  • 所以重载resolve会因为用户定义的转换函数不一样而混淆?
  • @AngelusMortis 基本上是的
  • A 中仍然有到B 的转换函数,只是删除B 中的构造函数是不行的。
  • @legends2k gcc 和 clangs 拒绝了代码,但 MS C++ 接受了代码并且选择的函数是 void func(B),正如我所期望的那样:)
  • @MM Sir 并没有声明“如果它们包含相同的用户定义的转换函数或构造函数”以某种方式限制我们 -> object-of-some-class-type 作为参数一些重载函数必须包含相同类型的转换函数(即构造函数或转换函数),因为它们必须是相同的 wrt 重载决议。谢谢
【解决方案2】:

所以顺序是 -> A() -> B::B(const A&) -> 标准转换(身份转换)

不!摘自标准(草案)[over.best.ics](强调我的):

  1. 如果需要 no 转换以将参数与参数类型匹配,则隐式转换序列是由恒等转换 (13.3.3.1.1) 组成的标准转换序列。

func(A()) 不是身份,它是用户定义的。同样来自标准,[[conv]]

对于类类型,也会考虑用户定义的转换;见 12.3。通常,隐式转换序列 (13.3.3.1) 由一个标准转换序列、一个用户定义的转换和另一个标准转换序列组成。

我认为您对标准转换存在误解。它们与用户定义的类型/类无关。标准转换仅适用于内置类型:左值到右值转换、数组到指针转换、函数到指针转换、整数提升、浮点提升、整数转换、浮点转换、浮点整数转换、指针转换、指向成员转换的指​​针、布尔转换和限定转换。 A -> int 不是这些,而是​​用户定义的转换。用户定义转换的标准,[[class.conv]] 即 12.3:

类对象的类型转换可以由构造函数和转换函数指定。这些转换称为用户定义的转换,用于隐式类型转换(第 4 条)、初始化(8.5)和显式类型转换(5.4、5.2.9)。

您有两个相同等级的用户定义转换序列(请参阅 M.M 的回答以了解原因),因此编译器希望您消除歧义。

【讨论】:

  • “您有两个用户定义的转换序列,因此排名相同” -> 我仍然不明白您如何将它们排名相同。如果您能用简单的术语解释一下,我将不胜感激:)
  • 转化可以按排名分类:精确匹配、促销和转化。你的两个电话都属于第三个。其中,两者都属于用户定义的转换类别。当两个用户定义的转换序列竞争时,标准中定义了选择哪一个。这部分标准在 M.M 的回答中被引用。
猜你喜欢
  • 1970-01-01
  • 2019-12-16
  • 1970-01-01
  • 1970-01-01
  • 2012-02-13
  • 1970-01-01
  • 2018-02-13
相关资源
最近更新 更多