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?
[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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With