Into the Extreme – Fold-Expressions
Tags: cpp, metaprogramming, cppsenioreas
Published: 2023-05-23 21:57:11

---
title: Into the Extreme – Fold-Expressions
published: true
date: 2023-05-22 09:00:00 UTC
tags: Cpp,Metaprogramming, CppSenioreas
canonical_url: https://cppsenioreas.wordpress.com/2023/05/22/into-the-extreme-fold-expressions/
---

Fold expressions exist in C++ since C++17 and significantly affect how we treat variadic templates. Back in the day, I wrote about [fold-expressions](https://dev.to/coralkashri/templates-infinity-theory-from-c-11-to-c-20-part-2-52l6-temp-slug-4490374) as part of the metaprogramming series, but today we will explore the extreme cases of fold-expression usages.

An important disclaimer before we start: In this article, code examples show variadic template usages with arguments passed by value, without forwarding them. This is done to simplify them and to focus on the idea behind the examples.

## Empty Variadic Parameters

In the case of a unary fold (fold expression without initialization), this case is legal for 3 types of operators: `&&`, `||`, and `,`.

### Operator &&

```

template <typename ...Args>
auto and_cond(Args... args) {
    return (args && ...);
}

```

In case of empty parameters (for the call `and_cond()`), the function will return `true`. A reasonable explanation for this decision might be that `&&` operator requires there won’t be any part that evaluates `false`. In this case, there are no parts at all, so none of the parts evaluates `false`, and therefore the result should be `true`.

### Operator ||

```

template <typename ...Args>
auto or_cond(Args... args) {
    return (args || ...);
}

```

In case of empty parameters, the function will return `false`. A reasonable explanation for this decision might be that `||` operator requires that at least one of the parts will evaluate `true`. Because there are no parts at all, none of them evaluates `true`, therefore the result is `false`.

### Operator ,

```

template <typename ...Args>
auto comma_op(Args... args) {
    return (args , ...);
}

```

For this case, when there are no parameters passed, the result will be `void()`.

### Other operators

For other operators, any call without parameters won’t compile.

## Variadic pack with a single parameter

Here things get a little bit unexpected. When passing only one parameter to a variadic pack, the result will ignore the operator and return the same type & parameter sent to the function (Tested on both gcc 13.1.0 & clang 16.0.0). For example:

```

template <typename ...Args>
auto func(Args ...args)
{
    return (args || ...);
}

int main() {
    using namespace std::string_literals;
    std::cout << func("I am a string"s); // Will print "I am a string"
    return EXIT_SUCCESS;
}

```

The generated code according to [C++ Insights](https://cppinsights.io/) is:

```

template<>
std::basic_string<char> func<std::basic_string<char>>(std::basic_string<char> __args0)
{
  return std::basic_string<char>(static_cast<std::basic_string<char>&&>(__args0));
}

```

The same would be for any other operator, including `+=`, `.*` and `->`.

## Binary fold expression without parameters

The same rules for a unary fold expression with a single parameter, are applied to a binary fold expression without parameters:

```

template <typename ...Args>
auto func(Args ...args)
{
    return (args ->* ... ->* "I am a string"s);
}

int main() {
    std::cout << func(); // Will print "I am a string"
    return EXIT_SUCCESS;
}

```

[C++ Insights](https://cppinsights.io/) generated code:

```

template<>
std::basic_string<char> func<>()
{
  return std::operator""s("I am a string", 13UL);
}

```

## Conclusion

We have to pay close attention to extreme cases and can never count on basic logic to be on our side (who would believe that we can send a std::string to a fold expression that uses `||` or `&&` operators?).

This article was inspired by a conversation between [Daisy Hollman](https://twitter.com/The_Whole_Daisy) and me. Thank you Daisy! ![❤](https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/2764.png)

An unrelated note: My articles’ publish rate decreased during the last several months. The reason is the preparations for [Daisy’s and mine talk](https://corecpp.org/schedule/#session-29) in [Core C++](https://corecpp.org/) (guess which conversation led to this article).