Section hub

std::ranges::views::adjacent_transform, std::ranges::adjacent_transform_view, std::ranges::views::pairwise_transform

  1. adjacent_transform_view is a range adaptor that takes a view and an invocable object fun, and produces a view whose ith element is a value that is the result of applying fun to each element in [i,i + N) of the original view. F always has arity N.

# Declarations

template< ranges::forward_range V, std::move_constructible F, std::size_t N >
requires ranges::view<V> && (N > 0) && std::is_object_v<F> &&
std::regular_invocable<F&,
/*REPEAT*/(ranges::range_reference_t<V>, N)...> &&
/*can-reference*/<std::invoke_result_t<F&,
/*REPEAT*/(ranges::range_reference_t<V>, N)...>>
class adjacent_transform_view
: public ranges::view_interface<adjacent_transform_view<V, F, N>>

(since C++23)

namespace views {
template< std::size_t N >
constexpr /* unspecified */ adjacent_transform = /* unspecified */;
}

(since C++23)

namespace views {
inline constexpr auto pairwise_transform = adjacent_transform<2>;
}

(since C++23)

Call signature
template< ranges::viewable_range R, class F >
requires /* see below */
constexpr ranges::view auto adjacent_transform<N>( R&& r, F&& fun );

(since C++23)

template< class F >
constexpr /*range adaptor closure*/ adjacent_transform<N>( F&& fun );

(since C++23)

# Notes

views::adjacent_transform only accepts foward ranges even when N is 0.

# Example

#include <array>
#include <iostream>
#include <ranges>
 
int main()
{
    constexpr static std::array data{1, 2, 3, 4, 5, 6};
    constexpr int window{3};
 
    auto Fun = [](auto... ints) { return (... + ints); };
    // Alternatively, the Fun could be any ternary (if window == 3) callable, e.g.:
    // auto Fun = [](int x, int y, int z) { return x + y + z; };
 
    constexpr auto view = data | std::views::adjacent_transform<window>(Fun);
 
    static_assert(
        view.size() == (data.size() - window + 1)
        && std::array{6, 9, 12, 15}
        == std::array{view[0], view[1], view[2], view[3]}
        && view[0] == Fun(data[0], data[1], data[2])
        && view[1] == Fun(data[1], data[2], data[3])
        && view[2] == Fun(data[2], data[3], data[4])
        && view[3] == Fun(data[3], data[4], data[5])
    );
 
    for (int x : view)
        std::cout << x << ' ';
    std::cout << '\n';
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
LWG 4098C++23views::adjacent_transform<0> used to accept input-only rangesmade rejected

# See also

This hub groups the ranges library by user task rather than by raw reference tree shape. View types and adaptor objects are presented as the same conceptual item.

Core adapters

Start here for the adapters most people reach for first when building pipelines.

Utility views

These adapt shape, ownership, or projection rather than representing the “headline” pipeline steps.

New in C++23 / C++26

Newer adapters, kept as a compact scan list with only standard badges.

All entities by category

A lighter-weight index of the full ranges surface, grouped by conceptual task instead of raw page-tree names.

74 entities