Pau*_*ton 19 c++ operator-overloading operators ternary-operator visual-c++
为什么不能使三元运算符超载?:'?
我经常使用三元运算符来合并if语句,并且很好奇为什么语言设计者选择禁止此运算符过载.我找到了解释为什么在C++运算符重载但未找到描述为什么这是不可能的解释.脚注提供的唯一信息是它不能超载.
我最初的猜测是,重载运算符几乎总是违反上面链接中给出的第一或第二原则.重载的含义很少是明显的或明显的,或者它将偏离其原始的已知语义.
所以我的问题更多的是为什么这不可能而不是如何,因为我知道它无法完成.
Mar*_*low 18
如果你可以覆盖三元运算符,你必须写这样的东西:
xxx operator ?: ( bool condition, xxx trueVal, xxx falseVal );
Run Code Online (Sandbox Code Playgroud)
打电话给你的覆盖,编译器必须能够计算两者的价值trueVal
和falseVal
.这不是内置三元运算符的工作方式 - 它只计算其中一个值,这就是为什么你可以编写如下内容的原因:
return p == NULL ? 23 : p->value;
Run Code Online (Sandbox Code Playgroud)
无需担心通过NULL指针间接.
Jam*_*nze 17
我认为当时的主要原因似乎不值得为该运算符发明新语法.没有令牌?:
,所以你必须为它创建一些特殊的语法规则.(当前的语法规则operator
后跟一个运算符,它是一个令牌.)
正如我们已经(从经验中)学到的更合理地使用运算符重载,很明显我们确实不应该允许重载&&
和||
其他任何响应指出的原因,也可能不是运算符逗号(因为重载版本不具有用户期望的序列点.所以支持它的动力甚至比最初的要少.
三元运算符的原理之一是仅基于条件表达式的真或假来评估真/假表达式.
cond ? expr1 : expr2
Run Code Online (Sandbox Code Playgroud)
在此示例expr1
中,仅评估if是否cond
为true,而expr2
仅评估if是否cond
为false.牢记这一点让我们看一下三元重载的签名是什么样的(为了简单起见,使用固定类型而不是模板)
Result operator?(const Result& left, const Result& right) {
...
}
Run Code Online (Sandbox Code Playgroud)
这个签名根本不合法,因为它违反了我所描述的确切语义.为了调用这种方法,语言必须对两者进行评估expr1
,expr2
因此不再对它们进行有条件的评估.为了支持三元运营商要么需要
expr1
或expr2
编辑
有些人可能认为在这种情况下缺乏短路是好的.原因是C++已经允许你违反运算符重载的短路||
和&&
Result operator&&(const Result& left, const Result& right) {
...
}
Run Code Online (Sandbox Code Playgroud)
虽然我仍然觉得这种行为令人困惑,即使对于C++也是如此.