Are fold expressions subject to short-circuiting?
Asked Answered
D

2

6

In C++17, are fold expressions subject to short-circuiting when used with && or || as their operator? If so, where is this specified?

Desiderative answered 1/5, 2018 at 4:15 Comment(4)
This answer states they are subject to short-circuiting, but it doesn't give any pointer to a standard text. I presume, however, that this is implicit (or defined) by the use of the boolean logic operators, as per this answer.Hamelin
Possible duplicate of Is short-circuiting logical operators mandated? And evaluation order?Hamelin
Disagree with the duplicate: it is not about fold expressions.Carillon
Possible duplicate of How to make `short-circuit evaluation` also available in `fold expressions`?Mulley
C
8

Yes, fold expressions using && or || as the operator can short-circuit, subject to the usual caveat that it happens for the built-in meaning, but not for an overloaded operator function.

The meaning of a fold-expression is defined in [temp.variadic]/9:

The instantiation of a fold-expression produces:

  • ((E_1 op E_2) op ...) op E_N for a unary left fold,

  • E_1 op (... op (E_N_minus_1 op E_N)) for a unary right fold,

  • (((E op E_1) op E_2) op ...) op E_N for a binary left fold, and

  • E_1 op (... op (E_N_minus_1 op (E_N op E))) for a binary right fold.

In each case, op is the fold-operator,....

Since the instantiation of the fold-expression is in terms of an expression containing the operator, all the normal rules for the operator, including overload resolution, order of evaluation, and short-circuiting when a built-in operator, apply.

Carillon answered 1/5, 2018 at 11:41 Comment(0)
N
-2

While @aschepler's answer is the specifically-correct one, I'd like to repeat a life-lesson I've shared regarding another fine technical point (tuple order of destruction):

If you can formulate, for multiple alternatives, a reasonable argument for why that alternative should be the one mandated by the standard - then you should not assume any of them is mandated (even if one of them happens to be).

In the context of fold expressions and short-circuit logic - it's already difficult enough to read variadic templated codel so I'd try saving the reader of my code the head-scratching regarding whether or not fold-short-circuiting happens...

If you can't avoid writing and and or folds, at least be generous with commenting regarding short-circuit behavior.

Neophyte answered 1/5, 2018 at 11:51 Comment(7)
IMHO that doesn't apply here. For std::tuple it is completely unspecified how the tuple elements are stored (are they data members of the tuple? data members of one or more base classes of the tuple? data members of some other data member of the tuple? Created using placement-new in untyped buffers of unsigned char?!). So you can't conclude anything about the order of initialization. For fold expressions the standard specifies the precise form of the expanded expression, so the usual semantics of the relevant operator apply.Jenn
@JonathanWakely: I can understand why you'd distinguish the two cases. However, the the standard could have said something else, e.g. "short-circuiting is a legacy feature of compatibility with C, which is why it never applies to overloaded operators; and since fold is not C-ish code, we don't need to support the short-circuiting quirk." That might not be what ended up happening, but it's not completely preposterous. Even the overloaded-vs-nonoverloaded short-circuit behavior is already confusing enough.Neophyte
The reason it doesn't apply to overloaded operators is nothing to do with dropping legacy C-ish stuff. I see where you're coming from, but thankfully C++ didn't make that choice: operators in fold expressions have the same meaning as operators outside fold expressions. The alternative would be awful IMHO.Jenn
@JonathanWakely: I'm not arguing against the decision of the standards committee. I'm just saying that it's not obvious enough that this is the only conceivable decision, hence when writing code it's best to not rely on the reader knowing what the decision was.Neophyte
And I think it's best to rely on what the language standard actually guarantees, not only what you can't imagine being defined any other way. If you always follow the "I can imagine it working differently, so I'll assume that could be true" then you are at the mercy of how creative your imagination is (and how uncreative other peoples' imaginations are!) and the "even if one of them happens to be" suggests actively ignoring what is guaranteed by the standard. I think your advice is well meaning, but not really a good rule of thumb.Jenn
By all means add a comment explaining the behaviour. But I strongly believe it's better to understand WTF you are doing, and how your tools work, not just shrug and say "it could work several different ways, so I'm not going to rely on something even if it's guaranteed to be true".Jenn
@JonathanWakely: You do have the slight bias of an experienced compiler developer who has an excellent grasp on everything. Knowing all of this is basically your job...Neophyte

© 2022 - 2024 — McMap. All rights reserved.