为什么转换构造函数优于转换运算符?

Ita*_*iwa 3 c++ explicit-constructor conversion-operator implicit-conversion

我有这个类SmallInt应该表示范围内的正整数值0-255- 包括:

struct SmallInt{
    explicit SmallInt(int x = 0) : iVal_( !(x < 0 || x > 255) ? x :
    throw std::runtime_error(std::to_string(x) + ": value outbounds!")){}
    operator int&() { return iVal_; }
    int iVal_;
};

int main(){

    try{
        SmallInt smi(7);
        cout << smi << '\n';
        cout << smi + 5 << '\n'; // 7 + 5 = 12
        cout << smi + 5.88 << '\n'; // 7.0 + 5.88 = 12.88
        smi = 33; // error: constructor is explicit
        smi.operator int&() = 33;
        cout << smi << '\n';
    }
    catch(std::runtime_error const& re){
        std::cout << re.what() << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 对我来说重要的是:为什么我可以分配给smi显式调用operator int&:smi.operator int&() = 33但不能隐式调用:smi = 33;

  • 第一个表达式 ( smi = 33;) 抱怨构造函数SmallInt(int)begin explicit;我知道这一点,但我有一个转换运算符,它返回一个可修改的普通左值。换句话说,为什么在这样的隐式赋值中,构造函数优于转换运算符?

Igo*_*nik 6

\n

[over.match.oper]/4对于内置赋值运算符,左操作数的转换受到如下限制:
\n...
\n(4.2) \xe2\x80\x94 不应用用户定义的转换到左侧操作数以实现与内置候选者最左侧\n参数的类型匹配。

\n
\n

因此,(int &)smi = 33该标准明确禁止考虑解释。

\n

  • 这讨论了重载解析,以及被视为重载解析的一部分的隐式转换序列。您当然可以显式转换。 (2认同)