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

- 13,776
- 2
- 47
- 72

- 13,567
- 17
- 59
- 76
-
2[This answer](https://stackoverflow.com/a/43048635/707650) 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](https://stackoverflow.com/a/628554/707650). – May 01 '18 at 04:21
-
1Possible duplicate of [Is short-circuiting logical operators mandated? And evaluation order?](https://stackoverflow.com/questions/628526/is-short-circuiting-logical-operators-mandated-and-evaluation-order) – May 01 '18 at 04:23
-
1Disagree with the duplicate: it is not about fold expressions. – aschepler May 01 '18 at 11:30
-
1Possible duplicate of [How to make \`short-circuit evaluation\` also available in \`fold expressions\`?](https://stackoverflow.com/questions/43047858/how-to-make-short-circuit-evaluation-also-available-in-fold-expressions) – HolyBlackCat May 01 '18 at 11:30
2 Answers
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
opE_2)
op ...)
opE_N
for a unary left fold,
E_1
op(
... op(E_N_minus_1
opE_N))
for a unary right fold,
(((E
opE_1)
opE_2)
op ...)
opE_N
for a binary left fold, and
E_1
op(
... op(E_N_minus_1
op(E_N
opE)))
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.
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.

- 118,144
- 57
- 340
- 684
-
3IMHO 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. – Jonathan Wakely May 01 '18 at 12:06
-
@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. – einpoklum May 01 '18 at 12:11
-
1The 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. – Jonathan Wakely May 01 '18 at 12:45
-
@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. – einpoklum May 01 '18 at 12:56
-
1And 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. – Jonathan Wakely May 01 '18 at 15:03
-
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". – Jonathan Wakely May 01 '18 at 15:05
-
@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... – einpoklum May 01 '18 at 15:12