General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
General | |||||||||||||||||||||||||||||||||||||||||||||||||||
Literals | |||||||||||||||||||||||||||||||||||||||||||||||||||
Operators | |||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||
Conversions | |||||||||||||||||||||||||||||||||||||||||||||||||||
Reduces (folds) apack over a binary operator.
Contents |
( pack op... ) | (1) | ||||||||
( ... op pack) | (2) | ||||||||
( pack op... op init) | (3) | ||||||||
( init op... op pack) | (4) | ||||||||
op | - | any of the following 32binary operators:+-*/%^&|=<><<>>+=-=*=/=%=^=&=|=<<=>>===!=<=>=&&||,.*->*. In a binary fold, bothops must be the same. |
pack | - | an expression that contains an unexpandedpack and does not contain an operator withprecedence lower than cast at the top level (formally, acast-expression) |
init | - | an expression that does not contain an unexpandedpack and does not contain an operator withprecedence lower than cast at the top level (formally, acast-expression) |
Note that the opening and closing parentheses are a required part of the fold expression.
The instantiation of afold expression expands the expressione as follows:
(E
op...)
becomes(E1
op(
...op(EN-1
opEN)))
(...
opE)
becomes(((E1
opE2)
op ...)
opEN)
(E
op...
opI)
becomes(E1
op(
...op(EN−1
op(EN
opI))))
(I
op...
opE)
becomes((((I
opE1)
opE2)
op ...)
opEN)
(whereN
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:
If the expression used asinit or aspack has an operator withprecedence below cast at the top level, it must be parenthesized:
template<typename...Args>int sum(Args&&...args){// return (args + ... + 1 * 2); // Error: operator with precedence below castreturn(args+ ...+(1*2));// OK}
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_fold_expressions | 201603L | (C++17) | Fold expressions |
#include <climits>#include <concepts>#include <cstdint>#include <iostream>#include <limits>#include <type_traits>#include <utility>#include <vector> // Basic usage, folding variadic arguments over operator<<template<typename...Args>void printer(Args&&...args){(std::cout<< ...<< args)<<'\n';} // Folding an expression that uses the pack directly over operator,template<typename...Ts>void print_limits(){((std::cout<<+std::numeric_limits<Ts>::max()<<' '), ...)<<'\n';} // Both a fold over operator&& using the pack// and over operator, using the variadic argumentstemplate<typename T,typename...Args>void push_back_vec(std::vector<T>& v, Args&&...args){ static_assert((std::is_constructible_v<T, Args&&>&& ...));(v.push_back(std::forward<Args>(args)), ...);} // Using an integer sequence to execute an expression// N times by folding a lambda over operator,template<class T,std::size_t...dummy_pack>constexpr T bswap_impl(T i,std::index_sequence<dummy_pack...>){ T low_byte_mask=static_cast<unsignedchar>(-1); T ret{};([&]{(void)dummy_pack; ret<<=CHAR_BIT; ret|= i& low_byte_mask; i>>=CHAR_BIT;}(), ...);return ret;} constexprauto bswap(std::unsigned_integralauto i){return bswap_impl(i,std::make_index_sequence<sizeof(i)>{});} int main(){ printer(1,2,3,"abc"); print_limits<uint8_t, uint16_t, uint32_t>(); std::vector<int> v; push_back_vec(v,6,2,45,12); push_back_vec(v,1,2,9);for(int i: v)std::cout<< i<<' ';std::cout<<'\n'; static_assert(bswap<std::uint16_t>(0x1234u)== 0x3412u); static_assert(bswap<std::uint64_t>(0x0123456789abcdefull)== 0xefcdab8967452301ULL);}
Output:
123abc255 65535 4294967295 6 2 45 12 1 2 9
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 2611 | C++17 | the expansion results of fold expressions were not enclosed with parentheses | enclosed with parentheses |