Why is it not possible to overload the ternary operator?

前端 未结 5 1695
时光说笑
时光说笑 2020-12-05 14:39

Why is it not possible to overload the ternary operator \' ?: \'?

I use the ternary operator often to consolidate if statements, and am curious why the language desi

相关标签:
5条回答
  • 2020-12-05 15:09

    The short and accurate answer is simply "because that's what Bjarne decided."

    Although the arguments about which operands should be evaluated and in what sequence give a technically accurate description of what happens, they do little (nothing, really) to explain why this particular operator can't be overloaded.

    In particular, the same basic arguments would apply equally well to other operators such as operator && and operator||. In the built-in version of each of these operators, the left operand is evaluated, then if and only if that produces 1 for && or a 0 for ||, the right operand is evaluated. Likewise, the (built in) comma operator evaluates its left operand, then its right operand.

    In an overloaded version of any of these operators, both operands are always evaluated (in an unspecified sequence). As such, they're essentially identical to an overloaded ternary operator in this respect. They all lose the same guarantees about what operands are evaluated and in what order.

    As to why Bjarne made that decision: I can see a few possibilities. One is that although it's technically an operator, the ternary operator is devoted primarily to flow control, so overloading it would be more like overloading if or while than it is like overloading most other operators.

    Another possibility would be that it would be syntactically ugly, requiring the parser to deal with something like operator?:, which requires defining ?: as a token, etc. -- all requiring fairly serious changes to the C grammar. At least in my view, this argument seems pretty weak, as C++ already requires a much more complex parser than C does, and this change would really be much smaller than many other changes that have been made.

    Perhaps the strongest argument of all is simply that it didn't seem like it would accomplish much. Since it is devoted primarily to flow control, changing what it does for some types of operands is unlikely to accomplish anything very useful.

    0 讨论(0)
  • 2020-12-05 15:13

    if you could override the ternary operator, you would have to write something like this:

    xxx operator ?: ( bool condition, xxx trueVal, xxx falseVal );
    

    To call your override, the compiler would have to calculate the value of both trueVal and falseVal. That's not how the built-in ternary operator works - it only calculates one of those values, which is why you can write things like:

    return p == NULL ? 23 : p->value;
    

    without worrying about indirecting through a NULL pointer.

    0 讨论(0)
  • 2020-12-05 15:15

    One of the principles of the ternary operator is that the true / false expression are only evaluated based on the truth or falseness of the conditional expression.

    cond ? expr1 : expr2
    

    In this example expr1 is only evaluated if cond is true while expr2 is only evaluated if cond is false. Keeping that in mind lets look at what a signature for ternary overloading would look like (using fixed types here instead of a template for simplicity)

    Result operator?(const Result& left, const Result& right) { 
      ...
    }
    

    This signature simply isn't legal because it violates the exact semantics I described. In order to call this method the language would have to evaluate both expr1 and expr2 hence they are no longer conditionally evaluated. In order to support ternary the operator would either need to

    1. Take a lambda for each value so it could produce them on demand. This would necessarily complicate the calling code though because it would have to take into account lambda call semantics where no lambda was logically present
    2. The ternary operator would need to return a value to denote whether the compiler should use expr1 or expr2

    EDIT

    Some may argue that the lack of short circuiting in this scenario is fine. The reason being that C++ already allows you to violate short circuiting in operator overloads with || and &&

    Result operator&&(const Result& left, const Result& right) { 
      ...
    }
    

    Though I still find this behavior baffling even for C++.

    0 讨论(0)
  • 2020-12-05 15:21

    For the same reason why you really should not (although you can) overload && or || operators - doing so would disable short-circuiting on those operators (evaluating only the necessary part and not everything), which can lead to severe complications.

    0 讨论(0)
  • 2020-12-05 15:22

    I think the main reason at the time that it didn't seem worth the effort of inventing a new syntax just for that operator. There is no token ?:, so you'd have to create a number of special grammar rules just for it. (The current grammar rule has operator followed by an operator, which is a single token.)

    As we've learned (from experience) to use operator overloading more reasonably, it has become apparent that we really shouldn't have allowed overloading of && and || either, for the reasons other responses have pointed out, and probably not operator comma as well (since the overloaded versions won't have the sequence point which the user expects). So the motivation to support it is even less than it was originally.

    0 讨论(0)
提交回复
热议问题