Home Item 16 - fold expressions (English)
Post
Cancel

Item 16 - fold expressions (English)

Scenario

Let’s start with a question: If we want to write a function to handle sum(1, 2) or sum(1.0, 2.0), we could write the following code to handle it.

1
2
3
4
5
6
7
8
9
auto sum(int a, int b)
{
    return a+b;
}

auto sum(double a, double b)
{
    return a+b;
}

However, this approach is cumbersome. Those familiar with the concept know that templates can handle the above scenario.

1
2
3
4
5
6
7
8
template<typename T1, typename T2>
auto sum(T1 a, T2 b) {
    return a + b;
}

sum(3, 4)
sum(2.5, 3.5)
sum(5, 2.5)

OK, now let’s extend the scenario. We want a function that can handle sum(a, b, c), sum(a, b, c, d), or even sum(a, b, c, d, e), and so on.

We know that the above template function can only handle two summable parameters. Are we supposed to write code for each case?

1
2
3
4
5
6
template<typename T1, typename T2, typename T3>

template<typename T1, typename T2, typename T3, typename T4>

...

C++17 fold expressions solve this problem.

Fold expressions

C++17 introduced fold expressions, a simple yet powerful way to handle variadic templates. Fold expressions allow you to expand a parameter pack and apply a binary operator in a concise manner.

There are four basic forms of fold expressions:

  1. Unary left fold: ( … op pack )
  2. Unary right fold: ( pack op … )
  3. Binary left fold: ( init op … op pack )
  4. Binary right fold: ( pack op … op init )

Here’s an example using a unary left fold to handle the sum function:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

template<typename... Args>
auto sum(Args... args) {
    return (... + args);
}

int main() {
    std::cout << "Sum: " << sum(1, 2, 3) << std::endl;
    std::cout << "Sum: " << sum(1, 2.2, 3.3, 4, 5) << std::endl;
    return 0;
}

Desktop View

local vairable in IDE

Desktop View

local vairable in IDE

Desktop View

Execution result

Desktop View

This syntax can also be used for operations like finding the product, maximum, and minimum values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <algorithm>


template<typename... Args>
auto sum(Args... args) {
    return (... + args);
}

template<typename... Args>
auto product(Args... args) {
    return (args * ...);
}

template<typename... Args>
auto max_value(Args... args) {
    return std::max({args...});
}

template<typename... Args>
auto min_value(Args... args) {
    return std::min({args...});
}

Give it a try and see how useful this syntax can be!

☝ツ☝

This post is licensed under CC BY 4.0 by the author.

👈 ツ 👍