C++17: Fold expressions

Fold expressions is the extension for already introduced variadic templates in C++11.

It allows to pack and unpack template parameters in unary and binary operations.

For example:

Example with pushing values:

Before C++17 template adding sum was:

 

Syntax for fold expressions:

( pack op … )             //(1)
( … op pack )             //(2)
( pack op … op init )     //(3)
( init op … op pack )     //(4)

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)

 

translation:

(… op pack) ==> ((pack1 op pack2 op …) op packN

(init op … op pack) ==> (((init op pack1) op pack2) op …) op packN

(pack op …) ==> pack1 op (… op (packN-1 op packN))

 

For example:

{1, 2, 3, 4} => args + …;  => 1 + (2 + (3 + 4))

Also, there are default values for empty parameter pack:

  • && — true
  • || — false
  • ,  — void()

Fold expressions in assembly

The code in C++17 looks simpler than in C++14

In C++14 we stack usage because of recursion like this each time:

but with optimization -O3 we will have avoided stack usage and only end value will be moved to std::cout.

in case of C++17:

There is no any recursion even without optimization level. In case of optimization -O3.

We will have the same assembly as for C++14:

Lambda inside fold expression

Example:

The standard paper related to Fold expressions: p0036r0

Leave a Reply

Your email address will not be published. Required fields are marked *