为什么下面带有非常量转换函数的代码没有歧义?

Why the following code with non-const conversion function is not ambiguous?

本文关键字:代码 歧义 函数 常量 非常 为什么 转换      更新时间:2023-10-16

考虑以下代码(取自 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

但是,正如注释所说,如果我从conversion函数中删除const,则会产生以下代码:

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

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

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

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

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

make(f)哪个重载更好?这是第二个,因为参数类型是非常量,与参数(f(更匹配,参数本身是非常量。

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

这确实不影响这一点,但这也不相关。

它确实影响的是参数 - 这是对this的隐式引用。隐式参数是常量成员函数的常量左值和非常量成员函数的非常量左值。参数是影响重载解析的因素。

在原始代码中,构造函数和转换运算符参数完全相同,因此从任何类型到任一参数的转换序列同样可取,因此不明确。

如果没有 constf,您的非常量左值表达式不需要任何转换,而构造函数确实需要转换为 const lvalue。因此,过载分辨率首选运算符。如果你写了const From f;,那么参数为 const 的构造函数将被选择,因为在这种情况下,non-const 转换运算符甚至不是有效的候选者。