- C++17 STL Cookbook
- Jacek Galowicz
- 378字
- 2025-04-04 19:00:06
There's more...
In case someone calls sum() with no arguments, the variadic parameter pack contains no values that could be folded. For most operators, this is an error (for some, it is not; we will see this in a minute). We then need to decide if this should stay an error or if an empty sum should result in a specific value. The obvious idea is that the sum of nothing is 0.
This is how it’s done:
template <typename ... Ts>
auto sum(Ts ... ts)
{
return (ts + ... + 0);
}
This way, sum() evaluates to 0, and sum(1, 2, 3) evaluates to (1 + (2 + (3 + 0))). Such folds with an initial value are called binary folds.
Again, it works if we write (ts + ... + 0), or (0 + ... + ts), but this makes the binary fold a binary right fold or a binary left fold again. Check out the following diagram:

When using binary folds in order to implement the no-argument case, the notion of an identity element is often important--in this case, adding a 0 to any number changes nothing, which makes 0 an identity element. Because of this property, we can add a 0 to any fold expression with the operators + or -, which leads to the result 0 in case there are no parameters in the parameter pack. From a mathematical point of view, this is correct. From an implementation view, we need to define what is correct, depending on what we need.
The same principle applies to multiplication. Here, the identity element is 1:
template <typename ... Ts>
auto product(Ts ... ts)
{
return (ts * ... * 1);
}
The result of product(2, 3) is 6, and the result of product() without parameters is 1.
The logical and (&&) and or (||) operators come with built-in identity elements. Folding an empty parameter pack with && results in true, and folding an empty parameter pack with || results in false.
Another operator that defaults to a certain expression when applied on empty parameter packs is the comma operator (,), which then defaults to void().
In order to ignite some inspiration, let's have a look at some more little helpers that we can implement using this feature.