Search code examples
c++implicit-conversionconversion-operatorexplicit-constructor

Why is the converting constructor preferred to the conversion operator?


I have this class SmallInt that should represent a positive integer value in the range 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';
    }
}
  • What matters me is: why can I assign to smi explicitly calling operator int&: smi.operator int&() = 33 but not implicitly: smi = 33;?

  • The first expression (smi = 33;) complains about the constructor SmallInt(int) begin explicit; I know that but I have the conversion operator that returns a modifiable plain lvalue. So in other words why in such an implicit assignment is the constructor preferred to the conversion operator?


Solution

  • [over.match.oper]/4 For the built-in assignment operators, conversions of the left operand are restricted as follows:
    ...
    (4.2) — no user-defined conversions are applied to the left operand to achieve a type match with the left-most parameter of a built-in candidate.

    Thus (int &)smi = 33 interpretation is explicitly prohibited from consideration by the standard.