我有这个类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';
}
}
重要的是:为什么我可以将显式调用
operator int&
分配给smi
:smi.operator int&() = 33
但不是隐式调用:smi = 33;
?第一个表达式(
smi = 33;
)抱怨构造函数SmallInt(int)
explicit
开头;我知道这一点,但我有一个转换运算符,它返回一个可修改的纯左值。换句话说,为什么在这样的隐式赋值中,构造函数优先于转换运算符?
[over.match.oper]/4对于内置赋值运算符,左操作数的转换限制如下:
...
(4.2) — 没有用户定义的转换应用于左侧操作数以实现与最左侧操作数的类型匹配 内置候选项的参数。
因此(int &)smi = 33
该标准明确禁止