【问题标题】:Why is the converting constructor preferred to the conversion operator?为什么转换构造函数优于转换运算符?
【发布时间】:2021-12-04 19:38:15
【问题描述】:

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

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';
    }
}
  • 我重要的是:为什么我可以分配给smi,显式调用operator int&amp;smi.operator int&amp;() = 33,但不能隐式调用:smi = 33;

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

【问题讨论】:

  • 这个问题应该有language-lawyer标签。
  • 疯狂猜测:33 的类型是 int&amp;&amp;,而不是 int&amp;
  • @Raildex 这是int 类型的prvalue。表达式不能有引用类型。
  • 我想smi = 33; 被解释为smi.operator=(33);,它必须将33 转换为SmallInt 才能传递参数,从而寻找合适的构造函数。
  • 如果你添加一个显式类型转换它可以工作:(int&amp;) smi = 33; 所以我猜它只会尝试转换 operator= 的右侧,因为你不想转换你的值想分配给

标签: c++ implicit-conversion conversion-operator explicit-constructor


【解决方案1】:

[over.match.oper]/4 对于内置赋值运算符,左操作数的转换限制如下:
...
(4.2) — 没有对左操作数应用用户定义的转换来实现与最左边的类型匹配 内置候选的参数。

因此,标准明确禁止对(int &amp;)smi = 33 的解释。

【讨论】:

  • 所以尽管static_cast&lt;int&amp;&gt;(smi) = 57; 有效。这是否意味着它是非标准的?我不应该那样做吗?
  • 这谈到了重载解决方案,以及被视为同一部分的隐式转换序列。您当然可以显式转换。
  • 好的,谢谢!
猜你喜欢
  • 2010-11-25
  • 2012-09-02
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 2016-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多