cpp20 · advanced
C++20 Ranges & views — Lazy Zero-Copy Pipelines
C++20 Ranges provides a composable, lazy pipeline for transforming sequences. A range is anything with begin()/end(); adaptors like views::filter, views::transform, views::take, and views::reverse compose with | and produce view objects — lightweight, non-owning descriptions of the computation. Nothing is computed until you iterate the view. This means a pipeline of N adaptors requires a single pass through the source data and zero temporary containers, unlike the classic STL approach of chaining algorithms with back_inserter. Ranges also work with infinite generators (views::iota) because of lazy evaluation. The std::ranges:: algorithms (sort, find_if, count_if) accept ranges directly without begin/end boilerplate and are constrained to the appropriate range category via concepts.
C++20 ranges pipeline: v | views::filter(pred) | views::transform(fn) | views::take(n) is lazy and zero-copy — the view object is built O(1); elements flow through the pipeline one at a time only when you iterate, with no temporary containers.
The code
#include <algorithm>#include <ranges>#include <vector>
std::vector<int> v = {1, 2, 3, 4, 5, 6};
// C++20 ranges pipeline — lazy, composable, readableauto result = v | std::views::filter([](int x) { return x % 2 == 0; }) | std::views::transform([](int x) { return x * x; }) | std::views::take(3);
// Lazy: NOTHING is computed until you iteratefor (int n : result) // only NOW each element flows through std::cout << n << ' '; // output: 4 16 36
// Views are non-owning references — no copies// Classic alternative needs 2 temp vectors + 2 passes
// Other useful adaptors:auto dropped = v | std::views::drop(2); // skip first 2auto reversed = v | std::views::reverse; // reversed viewauto zipped = std::views::zip(v, other); // C++23auto keys = map | std::views::keys; // map key viewWhat this lesson walks through
- 01The problem with classic STL algorithms
- 02Source data — a vector of 6 integers
- 03Build the pipeline — nothing computed yet
- 04filter(even) — pass only even numbers
- 05transform(x*x) — square each passing element
- 06take(3) + final output — only first 3 results materialise
- 07Key range adaptors every senior C++ engineer knows
With classic STL, filtering then transforming requires two passes and two temporary vectors. The code is also verbose — you lose the data-flow intent in iterator boilerplate. C++20 Ranges solves this with a composable, lazy, zero-copy pipeline.
See it animated — step by step, at your own pace
Unlock the full interactive walkthrough of C++20 Ranges & views — Lazy Zero-Copy Pipelines and 100+ animated C++ interview lessons.