fold expression

Reduces (folds) a parameter pack over a binary operator.

Syntax

( pack op ... ) (1) (since C++17)
( ... op pack ) (2) (since C++17)
( pack op ... op init ) (3) (since C++17)
( init op ... op pack ) (4) (since C++17)
1) unary right fold
2) unary left fold
3) binary right fold
4) binary left fold
op - any of the following 32 binary operators: + - * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->*. In a binary fold, both ops must be the same.
pack - an expression that contains an unexpanded parameter pack and does not contain an operator with precedence lower than cast at the top level (formally, a cast-expression)
init - an expression that does not contain an unexpanded parameter pack and does not contain an operator with precedence lower than cast at the top level (formally, a cast-expression)

Explanation

The instantiation of a fold expression expands the expression e as follows:

1) Unary right fold (E op ...) becomes E
1
op (... op (E
op E
N
))
2) Unary left fold (... op E) becomes ((E
1
op E
2
) op ...) op E
N
3) Binary right fold (E op ... op I) becomes E
1
op (... op (E
N−1
op (E
N
op I)))
4) Binary left fold (I op ... op E) becomes (((I op E
1
) op E
2
) op ...) op E
N

(where N is the number of elements in the pack expansion).

For example,

template<typename... Args>
bool all(Args... args) { return (... && args); }
 
bool b = all(true, true, true, false);
 // within all(), the unary left fold expands as
 //  return ((true && true) && true) && false;
 // b is false

When a unary fold is used with a pack expansion of length zero, only the following operators are allowed:

1) Multiplication (*). The value for the empty pack is 1
2) Addition (+). The value for the empty pack is int() (zero)
3) Bitwise AND (&). The value for the empty pack is -1 (bitwise all ones)
4) Bitwise OR (|). The value for the empty pack is int() (zero)
5) Logical AND (&&). The value for the empty pack is true
6) Logical OR (||). The value for the empty pack is false
7) The comma operator (,). The value for the empty pack is void()

Note

If the expression used as init or as pack has an operator with precedence below cast at the top level, it can be parenthesed:

template<typename ...Args>
int sum(Args&&... args) {
//    return (args + ... + 1 * 2); // Error: operator with precedence below cast
    return (args + ... + (1 * 2)); // OK
}

Example

#include <iostream>
template<typename ...Args>
void printer(Args&&... args) {
    (std::cout << ... << args) << '\n';
}
 
int main()
{
    printer(1, 2, 3, "abc");
}

Output:

123abc
doc_CPP
2016-10-11 09:58:41
Comments
Leave a Comment

Please login to continue.