CodeNebula
C++23stlexpert

std::ranges::adjacent_transform_view (C++23 Addition)

C++23 · Completing Modern · Compiler flag: -std=c++23

Explanation

View that applies a function to adjacent element pairs.

Real-World Scenario

Compute differences between consecutive sensor readings.

Quick Snippet

snippet.cpp
#include <ranges> auto atv = std::ranges::adjacent_transform_view<2>(vec, [](int a, int b) { return b - a; });

Full Example

ranges_adjacent_transform_view.cpp
// CodeNebula - C++23 Example: std::ranges::adjacent_transform_view
// Compile: g++ -std=c++23 -Wall -Wextra -o example ranges_adjacent_transform_view.cpp
// Note: Requires GCC 13+ / Clang 17+

// std::ranges::adjacent_transform_view<N> applies a function to each group of
// N adjacent elements. It combines adjacent_view with transform_view.
// views::pairwise_transform is an alias for adjacent_transform<2>.

#include <iostream>
#include <ranges>
#include <vector>
#include <cmath>

int main() {
    std::vector<int> nums = {1, 4, 9, 16, 25, 36};

    // Compute differences between consecutive elements
    std::cout << "=== Consecutive differences ===" << std::endl;
    auto diffs = std::views::adjacent_transform<2>(nums, [](int a, int b) {
        return b - a;
    });
    for (auto d : diffs) {
        std::cout << "  " << d;
    }
    std::cout << std::endl;

    // Compute running averages of pairs
    std::vector<double> temps = {20.5, 22.1, 19.8, 23.4, 21.0};
    std::cout << "\n=== Pairwise averages ===" << std::endl;
    auto avgs = std::views::adjacent_transform<2>(temps, [](double a, double b) {
        return (a + b) / 2.0;
    });
    for (auto avg : avgs) {
        std::cout << "  " << avg << std::endl;
    }

    // Three-element moving average
    std::cout << "\n=== 3-element moving average ===" << std::endl;
    auto moving_avg = std::views::adjacent_transform<3>(temps,
        [](double a, double b, double c) { return (a + b + c) / 3.0; }
    );
    for (auto avg : moving_avg) {
        std::cout << "  " << avg << std::endl;
    }

    // Detect local maxima using triple adjacency
    std::vector<int> signal = {1, 3, 2, 5, 4, 6, 1};
    std::cout << "\n=== Local maxima detection ===" << std::endl;
    auto is_peak = std::views::adjacent_transform<3>(signal,
        [](int left, int mid, int right) { return mid > left && mid > right; }
    );
    int idx = 1;
    for (auto peak : is_peak) {
        if (peak) std::cout << "  Peak at index " << idx << std::endl;
        ++idx;
    }

    // Euclidean distances between consecutive 1D points
    std::vector<double> points = {0.0, 3.0, 7.0, 8.0, 15.0};
    std::cout << "\n=== Distances between consecutive points ===" << std::endl;
    auto distances = std::views::adjacent_transform<2>(points,
        [](double a, double b) { return std::abs(b - a); }
    );
    for (auto d : distances) {
        std::cout << "  " << d << std::endl;
    }

    return 0;
}

// Expected output:
// === Consecutive differences ===
//   3  5  7  9  11
//
// === Pairwise averages ===
//   21.3
//   20.95
//   21.6
//   22.2
//
// === 3-element moving average ===
//   20.8
//   21.7667
//   21.4
//
// === Local maxima detection ===
//   Peak at index 1
//   Peak at index 3
//   Peak at index 5
//
// === Distances between consecutive points ===
//   3
//   4
//   1
//   7
Run command
g++ -std=c++23 -Wall -Wextra -o example ranges_adjacent_transform_view.cpp