[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
Related reading (internal links)
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.