[2026] C++ Range Adaptors | Pipeline Composition in C++20

[2026] C++ Range Adaptors | Pipeline Composition in C++20

이 글의 핵심

C++20 range adaptors: filter, transform, pipe syntax, lazy views, custom adaptors, and lifetime—how they relate to std::views.

What are range adaptors?

Function objects that transform a range into a view (C++20). 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

#include <ranges>
std::vector<int> v = {1, 2, 3, 4, 5};
// Adaptor: range -> view
auto filtered = v | std::views::filter([](int x) { return x > 2; });

Basic usage

아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

namespace vws = std::views;
std::vector<int> v = {1, 2, 3, 4, 5};
// Apply adaptor (functional style)
auto view1 = vws::filter(v, [](int x) { return x > 2; });
// Pipeline
auto view2 = v | vws::filter([](int x) { return x > 2; });

Practical examples

Example 1: Pipeline composition

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <ranges>
#include <vector>
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Several adaptors
auto pipeline = numbers
    | std::views::filter([](int x) { return x % 2 == 0; })  // evens
    | std::views::transform([](int x) { return x * x; })    // squares
    | std::views::take(3);                                   // first 3
for (int x : pipeline) {
    std::cout << x << " ";  // 4 16 36
}

Example 2: Reusable adaptors

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <ranges>
// Store adaptors
auto evenFilter = std::views::filter([](int x) { return x % 2 == 0; });
auto square = std::views::transform([](int x) { return x * x; });
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 = {6, 7, 8, 9, 10};
// Reuse
auto result1 = v1 | evenFilter | square;
auto result2 = v2 | evenFilter | square;

Example 3: Custom-style adaptors

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <ranges>
// Odds only
auto odds = std::views::filter([](int x) { return x % 2 != 0; });
// Multiples of 3
auto multiplesOf3 = std::views::filter([](int x) { return x % 3 == 0; });
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto result = v | odds;  // 1 3 5 7 9

Example 4: Conditional adaptor

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <ranges>
template<typename Range>
auto conditionalFilter(Range&& r, bool applyFilter) {
    if (applyFilter) {
        return std::forward<Range>(r) 
            | std::views::filter([](int x) { return x > 5; });
    } else {
        return std::forward<Range>(r) | std::views::all;
    }
}
int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    auto result = conditionalFilter(v, true);
    
    for (int x : result) {
        std::cout << x << " ";  // 6 7 8 9 10
    }
}

Main adaptors

다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace vws = std::views;
// Filtering
vws::filter(pred)
vws::take(n)
vws::drop(n)
vws::take_while(pred)
vws::drop_while(pred)
// Transform
vws::transform(func)
vws::reverse
// Split/join
vws::split(delimiter)
vws::join
// Generation
vws::iota(start)
vws::iota(start, end)
// Other
vws::all  // full range as view
vws::counted(it, n)
vws::common

Common problems

Problem 1: Type inference

아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// ❌ Verbose type
std::vector<int> v = {1, 2, 3};
std::ranges::filter_view<std::ranges::ref_view<std::vector<int>>, /* ....*/> filtered = 
    v | std::views::filter([](int x) { return x > 1; });
// ✅ auto
auto filtered = v | std::views::filter([](int x) { return x > 1; });

Problem 2: Adaptor order

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Order changes the result
auto r1 = v | std::views::reverse | std::views::take(3);
// 10 9 8
auto r2 = v | std::views::take(3) | std::views::reverse;
// 3 2 1

Problem 3: Lifetime

아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// ❌ Temporary destroyed
auto getView() {
    std::vector<int> v = {1, 2, 3};
    return v | std::views::filter([](int x) { return x > 1; });
    // v destroyed
}
// ✅ Clear ownership or reference
auto getView(const std::vector<int>& v) {
    return v | std::views::filter([](int x) { return x > 1; });
}

Problem 4: Performance

아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// Lazy: recomputed each pass
auto view = v | std::views::filter(pred) | std::views::transform(func);
for (int x : view) { /* ....*/ }  // compute
for (int x : view) { /* ....*/ }  // compute again
// ✅ Cache when you need one pass worth of work repeatedly
std::vector<int> cached(view.begin(), view.end());
for (int x : cached) { /* ....*/ }  // use cache
for (int x : cached) { /* ....*/ }  // use cache

Combining adaptors

아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace vws = std::views;
// Pipeline of adaptor objects
auto pipeline = vws::filter(pred) 
              | vws::transform(func) 
              | vws::take(n);
// Apply to data
std::vector<int> v = {1, 2, 3, 4, 5};
auto result = v | pipeline;

FAQ

Q1: What is a range adaptor?

A: It turns a range into a view.

Q2: Pipelines?

A: Combine with |.

Q3: Lazy evaluation?

A: Computed when you iterate.

Q4: Reuse?

A: You can store adaptor objects and reuse them.

Q5: Order?

A: It matters for correctness and efficiency.

Q6: Learning resources?

A:

  • “C++20 Ranges”
  • “C++20 The Complete Guide”
  • cppreference.com

Practical tips

Tips you can apply at work.

Debugging

  • When something breaks, check compiler warnings first
  • Reproduce with a small test case

Performance

  • Do not optimize without profiling
  • Define measurable targets first

Code review

  • Pre-check areas that often get flagged in review
  • Follow team conventions

Production checklist

Things to verify when applying this idea in practice.

Before coding

  • Is this technique the best fit for the problem?
  • Can teammates understand and maintain it?
  • Does it meet performance requirements?

While coding

  • Are all compiler warnings addressed?
  • Are edge cases considered?
  • Is error handling appropriate?

At review

  • Is intent clear?
  • Are tests sufficient?
  • Is it documented? Use this checklist to reduce mistakes and improve quality.

Keywords covered

Search for C++, range, adaptor, pipeline, C++20 to find this post.

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3