Skip to main content

Views and Pipelines

advanced11 min readLesson 151 of 204

A view is a non-owning range. Adaptors compose with |; nothing runs until you iterate.

The mental model

A view is a lightweight, non-owning wrapper over elements โ€” it presents data differently without copying it. Adaptation is lazy: building the pipeline does no work; iterating pulls elements through it.

namespace rv = std::views;

int total = 0;
for (int v : rv::iota(1, 11) | rv::filter([](int x) { return x % 2 == 0; })
                             | rv::transform([](int x) { return x * x; })) {
    total += v;
}
// total == 220 โ€” squares of 2,4,6,8,10, computed one element at a time

rv::iota(1, 11) is a generated range โ€” no vector exists. filter skips; transform maps; take/drop slice; reverse walks backwards. views::all(v) materializes a container into a view when you need the boundary.

Why pipelines win

  • No intermediate containers: chained algorithm calls would build a vector per stage; views build none.
  • Single pass composition: each element flows through the whole chain before the next one starts โ€” cache-friendly and early-exit-able (take(5) stops the whole pipeline).
  • Composability: the pipeline is a value; store it, pass it, reuse it.

The costs to respect

Iteration is not free (a filter+transform chain re-tests per element); deeply nested lambdas can hurt inlining; and โ€” the big one โ€” a view does not own what it points at. That is the next lessons' subject.

Now practice

Pipelines and ProjectionsCompose lazy pipelines and use projections with range algorithms โ€” no intermediate containers allowed.2 challenges ยท ยท ~22 min