3

User overloaded logical operators in C++ ( &&, ||) behave like regular functions. That is, both arguments in bool operator&&(const T &a, const T2 &b);are evaluated before entering the function, as entering a function is a sequence point[1] in C++. All good up to here.

Now, “builtin operators && and || perform short-circuit evaluation” [2][3], where there is a sequence point between the left and right sides. The cited reference isn’t clear what “builtin” are, only that they take bool operands, or convert them using “contextual conversion to bool”. It also mentions that only “two standard library classes overload these operators [because] the short-circuiting properties (...) do not apply to overloads, and because types with boolean semantics are uncommon.” [2]

Types with boolean semantics? How exactly do “builtin operators” work? Is it simply impossible to define logical operators with short-circuit evaluation?

[1] https://en.wikipedia.org/wiki/Sequence_point

[2] http://en.cppreference.com/w/cpp/language/operator_logical

[3] https://en.wikipedia.org/wiki/Short-circuit_evaluation

Ramon
  • 1,169
  • 11
  • 25
  • 4
    "Is it simply impossible to define logical operators with short-circuit evaluation?" Yes, it's "simply impossible". Your operator function needs both arguments, fully evaluated, which means the compiler simply can't do any short-circuiting. If you want short-circuit evaluation of a custom type of yours, then you need to implement conversion operators to `bool` instead of a logical operator. – Some programmer dude Mar 10 '16 at 14:10
  • 1
    My reading is that "builtin" refers to "this is a built-in language feature" as opposed to "this is part of the standard library". You can't make your own builtin operators, unless you make your own compiler with your own nonstandard extensions I guess. – Chris Beck Mar 10 '16 at 14:18
  • Possible duplicate of [Is there actually a reason why overloaded && and || don't short circuit?](http://stackoverflow.com/questions/25913237/is-there-actually-a-reason-why-overloaded-and-dont-short-circuit) – quamrana Mar 10 '16 at 15:17
  • @JoachimPileborg I think short-circuit can be implemented in user defined logical operations, that won't be trivial though – Slava Mar 11 '16 at 16:45

2 Answers2

5

You can imagine that a short-circuit && acts like this:

bool b = expr1 && expr2;

first, it takes expr1 and expr2 and stores them in lambdas:

bool b = and_helper( [&]{return expr1;}, [&]{return expr2;} );

and forwards them to a helper, where and_helper is (simplified slightly):

template<class Lhs, class Rhs>
bool and_helper( Lhs&& lhs, Rhs&& rhs ) {
  if (lhs()) return rhs();
  return false;
}

this has similar short-circuit behavior.

For user-overridden && to work this way, we'd have to auto-lambda the arguments and pass said lambdas into the user-written operator&&.

So the only barrier for this to happen with user-defined operations is syntactic. You can get the same behavior after a relatively mechanical transformation of your types, without resorting to magic.

The compiler just did a roughly equivalent operation (even before lambdas existed) when it ran into that construct.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

It means that short-circuiting doesn't apply to user-defined operators.

This is because, as you said, they behave like functions.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055