views::transform
C++23Apply a function to each element lazily.
Section hub
template< ranges::forward_range V, std::indirect_binary_predicate<iterator_t<V>,
ranges::iterator_t<V>> Pred >
requires ranges::view<V> && std::is_object_v<Pred>
class chunk_by_view
: public ranges::view_interface<chunk_by_view<V, Pred>>
(since C++23)
namespace views {
inline constexpr /* unspecified */ chunk_by = /* unspecified */ ;
}
(since C++23)
Call signature
template< ranges::viewable_range R, class Pred >
requires /* see below */
constexpr ranges::view auto chunk_by( R&& r, Pred&& pred );
(since C++23)
template< class Pred >
constexpr /*range adaptor closure*/ chunk_by( Pred&& pred );
(since C++23)
In order to provide the amortized constant time complexity required by the range concept, the result of begin() is cached within the chunk_by_view object. If the underlying range is modified after the first call to begin(), subsequent uses of the chunk_by_view object might have unintuitive behavior.
#include <functional>
#include <iostream>
#include <ranges>
#include <string_view>
void print_chunks(auto view, std::string_view separator = ", ")
{
for (auto const subrange : view)
{
std::cout << '[';
for (std::string_view prefix; auto const& elem : subrange)
std::cout << prefix << elem, prefix = separator;
std::cout << "] ";
}
std::cout << '\n';
}
int main()
{
std::initializer_list v1 = {1, 2, 3, 1, 2, 3, 3, 3, 1, 2, 3};
auto fn1 = std::ranges::less{};
auto view1 = v1 | std::views::chunk_by(fn1);
print_chunks(view1);
std::initializer_list v2 = {1, 2, 3, 4, 4, 0, 2, 3, 3, 3, 2, 1};
auto fn2 = std::ranges::not_equal_to{};
auto view2 = v2 | std::views::chunk_by(fn2);
print_chunks(view2);
std::string_view v3 = "__cpp_lib_ranges_chunk_by";
auto fn3 = [](auto x, auto y) { return not(x == '_' or y == '_'); };
auto view3 = v3 | std::views::chunk_by(fn3);
print_chunks(view3, "");
std::string_view v4 = "\u007a\u00df\u6c34\u{1f34c}"; // "zß水🍌"
auto fn4 = [](auto, auto ß) { return 128 == ((128 + 64) & ß); };
auto view4 = v4 | std::views::chunk_by(fn4);
print_chunks(view4, "");
}
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.
Start here for the adapters most people reach for first when building pipelines.
Apply a function to each element lazily.
Keep only elements that satisfy a predicate.
Keep the first N elements from a source range.
Skip the first N elements and expose the rest.
Split a range into non-overlapping fixed-size subranges.
Flatten a range of ranges into a single lazy sequence.
These adapt shape, ownership, or projection rather than representing the “headline” pipeline steps.
Normalize a range into a view-compatible form.
Adapt iterator/sentinel pairs into a common-range shape.
Wrap an existing range by reference.
Store and expose a range with unique ownership.
Package iterator + sentinel as a view-like object.
Project tuple-like elements to their key component.
Project tuple-like elements to their value component.
Newer adapters, kept as a compact scan list with only standard badges.
A lighter-weight index of the full ranges surface, grouped by conceptual task instead of raw page-tree names.