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 EN
for a unary left fold,E1 op (... op (EN-1 op EN))
for a unary right fold,(((E op E1) op E2) op ...) op EN
for a binary left fold, andE1 op (... op (EN-1 op (EN op E)))
for a binary right fold.In each case,
op
is the fold-operator,N
is the number of elements in the pack expansion parameters, and eachEi
is generated by instantiating the pattern and replacing each pack expansion parameter with itsi
th element. For a binary fold-expression,E
is 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 ] IfN
is 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