Modify the grammar of primary-expression in [expr.prim] to include fold expressions.
primary-expression:
fold-expression
Add the a new subsection to [expr.prim] called "Fold expressions".
A fold expression performs a fold of a template parameter pack ([temp.variadic]) over a binary operator.
fold-expression:
( cast-expression fold-operator ... )
( ... fold-operator cast-expression )
( cast-expression fold-operator ... fold-operator cast-expression )
fold-operator: one of
+ - * / % ^ & | ~ = < > << >>
+= -= *= /= %= ^= &= |= <<= >>=
== != <= >= && || , .* ->*
An expression of the form (... op e) where op is a fold-operator is
called a unary left fold.
An expression of the form (e op ...) where op is a fold-operator is
called a unary right fold.
Unary left folds and unary right folds are collectively called unary folds.
In a unary fold, the cast-expression shall contain an
unexpanded parameter pack.
An expression of the form (e1 op1 ... op2 e2) where op1 and op2 are fold-operators is
called a binary fold. In a binary fold, op1 and op2 shall be the same fold-operator,
and either e1 shall contain
an unexpanded parameter pack or e2 shall contain an unexpanded parameter
pack, but not both.
If e2 contains an unexpanded parameter pack, the expression is called a binary left fold.
If e1 contains an unexpanded parameter pack, the expression is called a binary right fold.
[ Example:
template<typename... Args>
bool f(Args... args) {
return (true + ... + args); // OK
}
template<typename... Args>
bool f(Args... args) {
return (args && ... && args); // error: both operands contain unexpanded parameter packs
}
— end example]
Add a new bullet to paragraph 4:
- In a fold-expression (5.1.3); the pattern is the cast-expression that contains an unexpanded parameter pack.
Change in paragraph 7:
The instantiation of a pack expansion that is
notneither a sizeof... expression nor a fold-expression produces a list E1, E2, ..., EN [...]
Add a new paragraph after paragraph 8:
The instantiation of a fold-expression produces:
((E1 op E2) op ...) op ENfor a unary left fold,E1 op (... op (EN-1 op EN))for a unary right fold,(((E op E1) op E2) op ...) op ENfor a binary left fold, andE1 op (... op (EN-1 op (EN op E)))for a binary right fold.In each case,
opis the fold-operator,Nis the number of elements in the pack expansion parameters, and eachEiis generated by instantiating the pattern and replacing each pack expansion parameter with itsith element. For a binary fold-expression,Eis generated by instantiating the cast-expression that did not contain an unexpanded parameter pack. [ Example:template<typename... Args> bool all(Args... args) { return (args && ...); } bool b = all(true, true, true, false);Within the instantiation of
all, the returned expression expands to((true && true) && true) && false, which evalutes tofalse. — end example ] IfNis zero for a unary fold-expression, the value of the expression is shown in Table N; if the operator is not listed in Table N, the instantiation is ill-formed.
Table N. Value of folding empty sequences Operator Value when parameter pack is empty * 1 + int() & -1 | int() && true || false , void()
Add a new paragraph after paragraph 6:
A fold-expression is type-dependent.
Change in paragraph 4:
Expressions of the following form are value-dependent:
sizeof...(identifier)fold-expression