[2026] C++ Views | Lazy Range Views in C++20
이 글의 핵심
C++20 std::views: lazy evaluation, filter, transform, take, drop, and pipeline composition with ranges—when views evaluate and common pitfalls.
What are views?
Lazy-evaluated ranges (C++20). 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <ranges>
std::vector<int> v = {1, 2, 3, 4, 5};
// View: no copy
auto filtered = v | std::views::filter([](int x) { return x > 2; });
// Evaluated on iteration
for (int x : filtered) {
std::cout << x << " "; // 3 4 5
}
Basic views
다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
namespace vws = std::views;
// filter: predicate
vws::filter([](int x) { return x % 2 == 0; })
// transform: map
vws::transform([](int x) { return x * 2; })
// take: first n elements
vws::take(5)
// drop: skip first n
vws::drop(3)
// reverse
vws::reverse
Practical examples
Example 1: filter
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <ranges>
#include <vector>
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Evens only
auto evens = numbers | std::views::filter([](int x) {
return x % 2 == 0;
});
for (int x : evens) {
std::cout << x << " "; // 2 4 6 8 10
}
Example 2: transform
아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> numbers = {1, 2, 3, 4, 5};
// Squares
auto squares = numbers | std::views::transform([](int x) {
return x * x;
});
for (int x : squares) {
std::cout << x << " "; // 1 4 9 16 25
}
Example 3: take & drop
아래 코드는 cpp를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// First 5
auto first5 = numbers | std::views::take(5);
// 1 2 3 4 5
// Skip first 3
auto skip3 = numbers | std::views::drop(3);
// 4 5 6 7 8 9 10
// Combined: skip 3, then take 5
auto middle = numbers | std::views::drop(3) | std::views::take(5);
// 4 5 6 7 8
Example 4: composite pipeline
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <ranges>
#include <vector>
#include <string>
struct Person {
std::string name;
int age;
};
std::vector<Person> people = {
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35},
{"David", 40}
};
// Age >= 30 -> names -> uppercase -> first 2
auto result = people
| std::views::filter([](const Person& p) { return p.age >= 30; })
| std::views::transform([](const Person& p) { return p.name; })
| std::views::transform([](std::string name) {
std::string upper = name;
for (char& c : upper) c = std::toupper(c);
return upper;
})
| std::views::take(2);
for (const auto& name : result) {
std::cout << name << std::endl; // BOB, CHARLIE
}
Conditional views
아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
namespace vws = std::views;
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// take_while: while predicate holds
auto lessThan5 = v | vws::take_while([](int x) { return x < 5; });
// 1 2 3 4
// drop_while: skip while predicate holds
auto from5 = v | vws::drop_while([](int x) { return x < 5; });
// 5 6 7 8 9 10
Common problems
Problem 1: Lifetime
다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ Dangling view
auto getView() {
std::vector<int> v = {1, 2, 3};
return v | std::views::filter([](int x) { return x > 1; });
// v destroyed
}
// ✅ Own the result
auto getFiltered() {
std::vector<int> v = {1, 2, 3};
std::vector<int> result;
auto view = v | std::views::filter([](int x) { return x > 1; });
std::ranges::copy(view, std::back_inserter(result));
return result;
}
Problem 2: Aliasing / mutation
아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Views do not copy the sequence
std::vector<int> v = {1, 2, 3};
auto view = v | std::views::transform([](int x) { return x * 2; });
v[0] = 10;
// view still refers to v
for (int x : view) {
std::cout << x << " "; // 20 4 6
}
Problem 3: Re-evaluation
아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
auto view = v | std::views::filter(pred) | std::views::transform(func);
// Recomputed each pass
for (int x : view) { /* ....*/ } // compute
for (int x : view) { /* ....*/ } // compute again
// ✅ Cache if needed
std::vector<int> cached(view.begin(), view.end());
Problem 4: Pipeline order
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// ❌ Less efficient
auto r1 = v
| std::views::transform([](int x) { return x * x; }) // 10 squares
| std::views::take(3); // use only 3
// ✅ Better order
auto r2 = v
| std::views::take(3) // 3 elements only
| std::views::transform([](int x) { return x * x; }); // 3 squares
Combining views
아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
namespace vws = std::views;
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Multiple adapters
auto result = v
| vws::filter([](int x) { return x % 2 == 0; }) // evens
| vws::transform([](int x) { return x * x; }) // squares
| vws::reverse // reverse
| vws::take(3); // first 3
// 100 64 36
FAQ
Q1: What are views?
A: Lazily evaluated range adapters.
Q2: Lazy evaluation?
A: Computation happens when you iterate.
Q2: Copying?
A: Views do not copy elements; they refer to the source.
Q4: Pipelines?
A: Combine with the | operator.
Q5: Performance?
A:
- No element copy by default
- Lazy evaluation
- Order of adapters matters
Q6: Learning resources?
A:
- “C++20 Ranges”
- “C++20 The Complete Guide”
- cppreference.com
Related reading (internal links)
Other posts that connect to this topic.
- C++ Ranges | range library guide
- C++ Ranges | functional-style C++20 guide
- C++ subrange | partial range guide
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.