为什么以下带有非常量转换功能的代码不是模棱两可的?

时间:2018-10-10 14:29:59

标签: c++ c++11 type-conversion operators

考虑以下代码(摘自https://en.cppreference.com/w/cpp/language/cast_operator

struct To {
    To() = default;
    To(const struct From&) {} // converting constructor
};

struct From {
    operator To() const {return To();} // conversion function
};

int main()
{
    From f;

    To t2 = f; // copy-initialization: ambiguous
// (note, if conversion function is from a non-const type, e.g.
//  From::operator To();, it will be selected instead of the ctor in this case)
}

正如评论所说,由于存在两个候选(转换函数和转换构造函数同等适用),因此以下行确实是模棱两可的

To t2 = f; //compile error

但是,如注释中所述,如果我从const函数中删除了conversion,则会导致以下代码:

struct From {
    operator To() {return To();} // conversion function
};

该调用编译良好。
const限定符不应影响conversion函数的返回值,那么为什么调用不再是模棱两可的?

2 个答案:

答案 0 :(得分:3)

  

const限定符不应影响转换函数的返回值,那么为什么调用不再是模棱两可的?

它不会影响结果,但是会影响选择最佳可行方法的重载分辨率。类似于这些组合函数的情况

To make(From const&);
To make(From&);

make(f)中哪个过载是更好的匹配?这是第二个,因为参数类型为非常量,可以更好地匹配非常量本身的参数(f)。

答案 1 :(得分:1)

  

const限定符不应影响转换函数的返回值

这并没有真正影响,但这也不相关。

它确实影响的是参数-这是对this的隐式引用。对于const成员函数,隐式参数是const左值;对于非const成员函数,隐式参数是非const。这些参数是影响过载解析的因素。

在原始代码中,构造函数和转换运算符的参数完全相同,因此从任何类型到任意一个参数的转换顺序都是同等可取的,因此模棱两可。

没有const,您的非const左值表达式f不需要任何转换,而构造函数则需要转换为const左值。这样,操作员是过载解决方案的首选。如果您写过const From f;,则将选择参数为const的构造函数,因为在这种情况下,非const转换运算符甚至都不是有效的候选对象。