Open In App

Types of Fold Expressions in C++ 17

Fold Expressions is a new feature of C++ 17, that allows us to create generic algorithms which can operate on any types and any number of inputs. They offer us a flexible, concise, and more efficient way to express what we’re trying to achieve with the code. In this article, we will discuss different types of Fold Expressions in C++17

Prerequisite: Fold Expression in C++



Types of Fold Expression

The fold expression can be classified into 4 types on the basis of the position of the parameter pack, operator and initial values. They are:

  1. Unary Left Fold
  2. Unary Right Fold
  3. Binary Left Fold
  4. Binary Right Fold

Let’s see each of them in detail.



1. Unary Left Fold Expressions

Unary Left Fold Expressions are those expressions in which the operators have left associativity i.e. while expanding the expression, the leftmost operator and operands will be evaluated first.

Syntax

(... pack op)

where

The above expression can also be expanded as:

((pack1 op pack2) op ...) op packN

where N is the number of parameters in the parameter pack.

Example




// C++ Program to Illustrate the Unary Left Fold Expression
#include <iostream>
using namespace std;
  
//* Left Associative that is, UNARY LEFT fold
template <typename... Args>
auto diffFromLeft(Args... args)
{
    return (... - args);
}
  
// driver code
int main()
{
    int result = diffFromLeft(2, 3, 5, 7);
    cout << result << endl;
    return 0;
}

Output

-13

Explanation

In the above program, the parameters were {2, 3, 5, 7}, and the fold expression used was (… – args) i.e. unary left fold expression. So, the expansion of the expression will be:

(((2 - 3) - 5) - 7)

which is -13.

2. Unary Right Fold Expression

The Unary Right Fold Expressions are opposite to the left fold expression i.e. they are right-associative. It means that the expression is evaluated from Right to Left.

Syntax

(pack op ...)

where

The right fold expression will be expanded as:

(pack1 op (... op (packN-1 op packN)))

Example




// C++ Program to Illustrate the
#include <iostream>
using namespace std;
  
//* Right Associative that is, UNARY RIGHT FOLD
template <typename... Args>
auto diffFromRight(Args... args)
{
    return (args - ...);
}
  
// driver code
int main()
{
    int result = diffFromRight(2, 3, 5, 7);
    cout << result << endl;
    return 0;
}

Output

-3

Explanation

The fold expression is (args – …) which is the right fold expression, so the expansion of the arguments {2, 3, 5, 7} will be different from the previous expression.

(2 - (3 - (5 - 7)))

which is -3.

3. Binary Left Fold Expression

Binary Left Fold Expressions have similar associativity as unary left-fold expressions i.e. left-to-right associativity but there is one more argument which is the initial value.

Syntax

(init op ... op pack)

where

Note: The initial value is useful in cases to avoid errors where the parameter pack does not have any parameters.

Example




// C++ program to illustrate the binary left fold expression
#include <iostream>
  
using namespace std;
  
// function template with parameter pack
template <typename... Args>
auto subtract(Args... args)
{
    // Binary left fold
    return (0 - ... - args);
}
  
// driver code
int main()
{
    cout << "Result With Arguments:" << subtract(2, 3, 5, 7)
         << endl;
    cout << "Result Without Arguments: " << subtract()
         << endl;
    return 0;
}

Result With Arguments:-17
Result Without Arguments: 0

Explanation

The expression is (0 – … – args) which is a binary left-fold expression. The expansion of the parameters {2, 3, 5, 7} will be similar to the unary left fold expression but there will be additional argument at the start.

((((0 - 2) - 3) - 5) - 7)

which is -17.

4. Binary Right Fold Expression

Binary right-fold expressions have RIGHT to LEFT Associativity and an additional argument – initial value.

Syntax

(args - ... - op)

where

Example




// C++ program to illustrate binary right fold expresssion
#include <iostream>
using namespace std;
  
template <typename... Args>
auto diffFromRight(Args... args)
{
    return (args - ... - 24);
}
  
// driver
int main()
{
    cout << diffFromRight(2, 3, 5, 7) << endl;
    return 0;
}

Output

21

Explanation

The expansion of the expression present in the article (binary right-fold expression) will be:

(2 - (3 - (5 - (7 - 21))))

Article Tags :