Why is it impossible to overload the ternary operator?

Why is it impossible to overload the ternary operator ??: ??

I often use the ternary operator to consolidate if statements, and I'm curious why the language developers decided to prohibit overloading this operator. I was looking for an explanation why in C ++ Operator Overloading , but could not find a description of why this is not possible. The only information that a footnote provides is that it cannot be overloaded.

My initial guess is that overloading an operator will almost always violate the number one or two of the principles given in the link above. The meaning of overload will rarely be obvious or clear, or it will deviate from its original known semantics.

So my question is why this is not possible, and not how, because I know that it is impossible.

+16
source share
5 answers

I think that the main reason at the time when it did not seem worthwhile was an attempt to invent a new syntax only for this operator. No Token ?: So you will need to create some special grammar rules just for this. (The current grammar rule has an operator followed by an operator, which is a single token.)

As we learned (from experience) to use operator overloading more wisely, it became obvious that we really shouldn't allow overloading && and || either for the reason other answers were indicated, and probably not an operator comma (since overloaded versions will not have a sequence point that the user expects). So, the motivation for support is even less than it was originally.

+16
source

if you can override the ternary operator, you need to write something like this:

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

To invoke your override, the compiler will need to compute both trueVal and falseVal . This is not how the built-in ternary operator works - it only calculates one of these values, so you can write things like:

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

without worrying about indirection with a NULL pointer.

+14
source

One of the principles of the ternary operator is that true / false expression is evaluated only on the basis of the truth or falsity of the conditional expression.

 cond ? expr1 : expr2 

In this example, expr1 is evaluated only if cond is true, and expr2 is evaluated only if cond is false. Keeping this in mind, let's see what the signature for triple overload will look like (for simplicity, use fixed types here instead of the template)

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

This signature is simply not legal, as it violates the exact semantics that I described. To call this method, the language would have to evaluate both expr1 and expr2 , therefore, they are no longer subject to conditional evaluation. To support the triple operator, either

  • Take a lambda for each value so that it can produce them on demand. This would certainly complicate the calling code, though, since it would have to take into account the semantics of lambda calls where there was no lambda logically
  • The ternary operator will need to return a value to indicate whether the compiler should use expr1 or expr2

EDIT

Some may argue that the absence of a short circuit in this scenario is excellent. The reason is that C ++ already allows you to break a short circuit during operator overloads with || and &&

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

Although I still find this behavior perplexing even for C ++.

+6
source

For the same reason why you really shouldn't (though you can) overload the && or || - this will lead to the disconnection of a short circuit on these operators (evaluation of only the necessary part, and not the whole), which can lead to serious complications.

+1
source

The short and accurate answer is simply "because Bjarn decided it."

Although the arguments about which operands should be evaluated and in what sequence provide a technically accurate description of what is happening, they do little (really, nothing) explain why this particular operator cannot be overloaded.

In particular, the same basic arguments apply equally to other operators, such as operator && and operator|| . In the built-in version of each of these operators, the left operand is evaluated if and only if it produces 1 for && or 0 for || , evaluates the right operand. Similarly, 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). Thus, they are essentially identical to the overloaded ternary operator in this regard. They all lose the same guarantees about which operands are evaluated and in what order.

As to why Bjarn made this decision: I see several possibilities. The first is that, although it is technically an operator, the ternary operator is primarily dedicated to flow control, so overloading it will be more like overloading if or while than it would overload most other operators.

Another possibility would be that it would be syntactically ugly, requiring the parser to deal with something like operator?: that requires defining ?: As a token, etc. - all that require quite serious changes in the grammar of C. At least in my opinion, this argument seems rather weak, since C ++ already requires a much more complex parser than C, and this change is really much less than many others changes that have been made.

Perhaps the strongest argument of all is that it seemed that this would not be done. Since it focuses primarily on flow control, changing what it does for some types of operands is unlikely to bring anything very useful.

+1
source

All Articles