Do overloaded logical operators && and || short-circuit since C++17?
Asked Answered
M

1

16

I read in http://en.cppreference.com/w/cpp/language/operators:

The boolean logic operators, operator && and operator ||

Unlike the built-in versions, the overloads do not sequence their left operand before the right one, and (until C++17) cannot implement short-circuit evaluation.

(My emphasis).

Couldn't find any resource or code example for C++17 supporting short-circuit for operator&& and operator||. Is it related to C++17 parameter pack fold expression? tried to play with it but couldn't create short circuit behavior for overloaded operator && and || with C++17 fold expression.

Code:

class A {
    bool val;
public:
    A(bool b) : val(b) { cout << "A born as " << boolalpha << val << endl;}
    template<typename ...Args>
    bool operator&&(Args&&... args) {
        return (val && ... && args.val);
    }    
};

int main() {
    cout << boolalpha;
    cout << ( A{false} && A{true} ) << endl;
    cout << ( A{true} && A{false} ) << endl;
    cout << ( A{false} && A{false} ) << endl;
}

Output:

A born as true
A born as false
false
A born as false
A born as true
false
A born as false
A born as false
false

http://coliru.stacked-crooked.com/a/f0b5325899c2fe6b

Note: the sequence of left to right is also not happening in current gcc version, compiled with C++17 flag.

Maybellemayberry answered 19/12, 2016 at 16:49 Comment(7)
Please show what you've tried that didn't work. Perhaps you can select the compiler and version you used here and post the link.Dulcinea
couldn't create short circuit behavior What was the error? Or was there no error and you had side effects that exhibited themselves for the downstream operators? Or did you step through the code and it stepped into the other operators?Dulcinea
@Mus The question is about the behavior defined in the standard, not about code that doesn't work.Cilice
I think this is what you are looking.Mauceri
This (until c++17) mark applies to “do not sequence their left operand before the right one, and”. In C++17, a call to overloaded operator function is sequenced in the same way as the corresponding built-in operator. AFAIK you still can't create short circuit behavior.Snare
Regardless, operator&&() can take exactly one argument, so writing it as a variadic template is somewhat misleading.Ridglee
@Barry: good point. Of course this can be tested also with regular operator overloading, same result - sequence of left to right still not implemented in current gcc version: coliru.stacked-crooked.com/a/754a27e8541ad075Maybellemayberry
V
14

That statement is not about short-circuit evaluation. It's about the order of evaluating the operands.

Pre-C++17, the order for evaluating the operands of overloaded && and || was compiler-defined. C++17 defines an explicit order of evaluation of left-to-right for && and ||, whether they are overloaded or not.

Short circuit evaluation still only applies to the built-in operators.

Note that on the actual page you cited, the part that is highlighted is what is applied to a specific version. That part is about the sequencing order, not the part about short-circuit evaluation.

Violation answered 19/12, 2016 at 17:4 Comment(5)
That's an unfortunate placement of the "until c++17" tag. I've edited the page to make the grammar clearer.Dependable
@user2357112: Personally, it seems fine so long as you know that all of the version-specific tags only apply to the text in the box containing them.Violation
Of course, not everyone knows that, and the mismatch between the English grammar and the version-box can still throw off someone who knows how the version-boxes work.Dependable
@user2357112: Isn't the example (compiled with C++17 flag) showing right operand being evaluated first? Is it against the sequence note for C++17?Maybellemayberry
@AmirKirsh: It's probably just not implemented yet.Dependable

© 2022 - 2024 — McMap. All rights reserved.