# Folding expressions

Andrew Sutton, Richard Smith
Date: 2014-11-07
Document number: N4295
Revises: N4191

## Wording

### 5.1. Primary expressions [expr.prim]

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".

#### 5.1.3 Fold expressions [expr.prim.fold]

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, and
• `E1 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 each `Ei` is generated by instantiating the pattern and replacing each pack expansion parameter with its `i`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 to `false`. — end example ] If `N` 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()

#### 14.6.2.2 Type-dependent expressions [temp.dep.expr]

Add a new paragraph after paragraph 6:

A fold-expression is type-dependent.

#### 14.6.2.3 Value-dependent expressions [temp.dep.constexpr]

Change in paragraph 4:

Expressions of the following form are value-dependent:

`sizeof...(` identifier `)`

fold-expression