C++23stlexpert
std::ranges::fold_left, fold_right, fold_left_first, fold_right_last (C++23 Addition)
C++23 · Completing Modern · Compiler flag: -std=c++23
Explanation
Algorithms to fold a range left or right, with or without the first/last element.
Real-World Scenario
Compute cumulative scores in a game with custom operations.
Quick Snippet
snippet.cpp
#include <ranges> auto sum = std::ranges::fold_left(vec, 0, std::plus{});Full Example
ranges_fold.cpp
// CodeNebula - C++23 Example: ranges::fold_left, fold_right, fold_left_first, fold_right_last
// Compile: g++ -std=c++23 -Wall -Wextra -o example ranges_fold.cpp
// Note: Requires GCC 13+ / Clang 17+
// C++23 introduces fold algorithms for ranges. fold_left processes left-to-right
// with an initial value. fold_right processes right-to-left. fold_left_first and
// fold_right_last use the first/last element as the initial value.
#include <iostream>
#include <algorithm>
#include <ranges>
#include <vector>
#include <string>
#include <functional>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
// fold_left: left-to-right reduction with initial value
std::cout << "=== fold_left ===" << std::endl;
auto sum = std::ranges::fold_left(nums, 0, std::plus{});
std::cout << " Sum: " << sum << std::endl;
auto product = std::ranges::fold_left(nums, 1, std::multiplies{});
std::cout << " Product: " << product << std::endl;
// fold_left with string concatenation (shows left-to-right order)
std::vector<std::string> words = {"A", "B", "C", "D"};
auto concat_left = std::ranges::fold_left(words, std::string("("),
[](std::string acc, const std::string& w) { return acc + w + " "; });
std::cout << " Left concat: " << concat_left << ")" << std::endl;
// fold_right: right-to-left reduction with initial value
std::cout << "\n=== fold_right ===" << std::endl;
auto concat_right = std::ranges::fold_right(words, std::string(")"),
[](const std::string& w, std::string acc) { return " " + w + acc; });
std::cout << " Right concat: (" << concat_right << std::endl;
auto right_sub = std::ranges::fold_right(nums, 0,
[](int val, int acc) { return val - acc; });
std::cout << " Right subtraction (1-(2-(3-(4-(5-0))))): " << right_sub << std::endl;
// fold_left_first: uses first element as initial value
std::cout << "\n=== fold_left_first ===" << std::endl;
auto max_val = std::ranges::fold_left_first(nums,
[](int a, int b) { return a > b ? a : b; });
if (max_val) std::cout << " Max: " << *max_val << std::endl;
auto min_val = std::ranges::fold_left_first(nums,
[](int a, int b) { return a < b ? a : b; });
if (min_val) std::cout << " Min: " << *min_val << std::endl;
// fold_left_first on empty range returns std::optional with no value
std::vector<int> empty;
auto empty_result = std::ranges::fold_left_first(empty, std::plus{});
std::cout << " Empty fold has value: " << std::boolalpha
<< empty_result.has_value() << std::endl;
// fold_right_last: uses last element as initial value
std::cout << "\n=== fold_right_last ===" << std::endl;
auto right_max = std::ranges::fold_right_last(nums,
[](int val, int acc) { return val > acc ? val : acc; });
if (right_max) std::cout << " Max (right): " << *right_max << std::endl;
// Practical: build a sentence
std::vector<std::string> parts = {"The", "quick", "brown", "fox"};
auto sentence = std::ranges::fold_left(parts, std::string{},
[](std::string acc, const std::string& w) {
return acc.empty() ? w : acc + " " + w;
});
std::cout << "\n=== Practical: build sentence ===" << std::endl;
std::cout << " " << sentence << std::endl;
return 0;
}
// Expected output:
// === fold_left ===
// Sum: 15
// Product: 120
// Left concat: (A B C D )
//
// === fold_right ===
// Right concat: ( A B C D)
// Right subtraction (1-(2-(3-(4-(5-0))))): 3
//
// === fold_left_first ===
// Max: 5
// Min: 1
// Empty fold has value: false
//
// === fold_right_last ===
// Max (right): 5
//
// === Practical: build sentence ===
// The quick brown fox
Run command
g++ -std=c++23 -Wall -Wextra -o example ranges_fold.cpp