Using Fold with Custom Data Types

Can fold_left() and fold_right() be used with custom data types?

Yes, fold_left() and fold_right() can be used with custom data types, provided that the custom data type supports the required binary operation.

Requirements for Custom Data Types

  • The custom data type must support the operation used in the fold function. This means that if you are using std::plus<>, your custom type must have an operator+.
  • The initial value and the elements in the range must be compatible with the binary operation.

Example

Let's create a custom data type Accumulator that supports the addition operation. We'll use this type with fold_left() to demonstrate how folding works with custom data types.

#include <algorithm>
#include <iostream>
#include <vector>

struct Accumulator {
  int sum;
  int count;

  Accumulator operator+(int n) const {
    return Accumulator{sum + n, count + 1}; }

  void log() const {
    std::cout << "Count: " << count
      << "\nSum: " << sum << "\n";
  }
};

int main() {
  std::vector<int> numbers{1, 2, 3, 4, 5};

  Accumulator result = std::ranges::fold_left(
    numbers, Accumulator{}, std::plus<>());

  result.log();
}
Count: 5
Sum: 15

Explanation

  • The Accumulator struct has two members: sum and count.
  • We define the operator+ to allow adding an integer to an Accumulator object, which updates the sum and count.
  • The log() function is used to print the current state of the Accumulator.

In the main() function, we use std::ranges::fold_left() to combine elements of the numbers vector using an Accumulator as the initial value. The custom operator+ ensures that each element of the vector is added to the Accumulator, updating the sum and count accordingly.

Using Different Operations

You can also define other operations for your custom data types. For example, if you have a custom type that represents a complex number, you can define an operator* for multiplication and use it with fold_left().

#include <algorithm>
#include <iostream>
#include <vector>

struct Complex {
  double real;
  double imag;

  Complex operator*(const Complex& other) const {
    return Complex{
      real * other.real - imag * other.imag,
      real * other.imag + imag * other.real
    };
  }
};

int main() {
  std::vector<Complex> numbers{
    {1, 2}, {3, 4}, {5, 6}};

  Complex initial{1, 0};
  Complex result = std::ranges::fold_left(
    numbers, initial, std::multiplies<>());

  std::cout << "Result: (" << result.real
    << ", " << result.imag << ")";
}
Result: (-85, 20)

In summary, fold_left() and fold_right() can be used with custom data types as long as the required operations are defined. This allows for flexible and powerful ways to process collections of custom objects.

C++23 Fold Algorithms

An introduction to the 6 new folding algorithms added in C++23, providing alternatives to std::reduce and std::accumulate

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Difference Between Reduce and Fold Algorithms
What is the difference between std::reduce() and the new fold algorithms introduced in C++23?
Choosing Between Fold Left and Fold Right
How do I decide whether to use fold_left() or fold_right()?
Advantages of Fold Algorithms
What are the advantages of using fold_left() over accumulate()?
Using Custom Operators with Fold
How do I use fold_left_first() with custom operators?
Initial Value in Fold Algorithms
What happens if the initial value provided to fold_left() is not the identity of the operation?
Practical Applications of Fold Algorithms
What are some practical applications of fold algorithms in real-world programming?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant