C++ Views | "뷰" 가이드
이 글의 핵심
C++ Views에 대한 실전 가이드입니다. 개념부터 실무 활용까지 예제와 함께 상세히 설명합니다.
Views란?
지연 평가 범위 (C++20)
#include <ranges>
std::vector<int> v = {1, 2, 3, 4, 5};
// 뷰: 복사 없음
auto filtered = v | std::views::filter( { return x > 2; });
// 순회 시 평가
for (int x : filtered) {
std::cout << x << " "; // 3 4 5
}
기본 뷰
namespace vws = std::views;
// filter: 조건 필터
vws::filter( { return x % 2 == 0; })
// transform: 변환
vws::transform( { return x * 2; })
// take: 처음 n개
vws::take(5)
// drop: 처음 n개 제외
vws::drop(3)
// reverse: 역순
vws::reverse
실전 예시
예시 1: filter
#include <ranges>
#include <vector>
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 짝수만
auto evens = numbers | std::views::filter( {
return x % 2 == 0;
});
for (int x : evens) {
std::cout << x << " "; // 2 4 6 8 10
}
예시 2: transform
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 제곱
auto squares = numbers | std::views::transform( {
return x * x;
});
for (int x : squares) {
std::cout << x << " "; // 1 4 9 16 25
}
예시 3: take & drop
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 처음 5개
auto first5 = numbers | std::views::take(5);
// 1 2 3 4 5
// 처음 3개 제외
auto skip3 = numbers | std::views::drop(3);
// 4 5 6 7 8 9 10
// 조합: 3개 제외 후 5개
auto middle = numbers | std::views::drop(3) | std::views::take(5);
// 4 5 6 7 8
예시 4: 복합 파이프라인
#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}
};
// 30세 이상 -> 이름만 -> 대문자 -> 처음 2개
auto result = people
| std::views::filter( { return p.age >= 30; })
| std::views::transform( { return p.name; })
| std::views::transform( {
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
}
조건부 뷰
namespace vws = std::views;
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// take_while: 조건 만족하는 동안
auto lessThan5 = v | vws::take_while( { return x < 5; });
// 1 2 3 4
// drop_while: 조건 만족하는 동안 제외
auto from5 = v | vws::drop_while( { return x < 5; });
// 5 6 7 8 9 10
자주 발생하는 문제
문제 1: 수명
// ❌ 댕글링 참조
auto getView() {
std::vector<int> v = {1, 2, 3};
return v | std::views::filter( { return x > 1; });
// v 소멸
}
// ✅ 소유
auto getFiltered() {
std::vector<int> v = {1, 2, 3};
std::vector<int> result;
auto view = v | std::views::filter( { return x > 1; });
std::ranges::copy(view, std::back_inserter(result));
return result;
}
문제 2: 복사
// 뷰는 복사 안 함
std::vector<int> v = {1, 2, 3};
auto view = v | std::views::transform( { return x * 2; });
v[0] = 10;
// view는 v 참조
for (int x : view) {
std::cout << x << " "; // 20 4 6
}
문제 3: 재평가
auto view = v | std::views::filter(pred) | std::views::transform(func);
// 매번 재계산
for (int x : view) { /* ... */ } // 계산
for (int x : view) { /* ... */ } // 다시 계산
// ✅ 캐싱
std::vector<int> cached(view.begin(), view.end());
문제 4: 파이프 순서
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// ❌ 비효율
auto r1 = v
| std::views::transform( { return x * x; }) // 10개 제곱
| std::views::take(3); // 3개만 사용
// ✅ 효율적
auto r2 = v
| std::views::take(3) // 3개만
| std::views::transform( { return x * x; }); // 3개만 제곱
뷰 조합
namespace vws = std::views;
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 여러 뷰 조합
auto result = v
| vws::filter( { return x % 2 == 0; }) // 짝수
| vws::transform( { return x * x; }) // 제곱
| vws::reverse // 역순
| vws::take(3); // 처음 3개
// 100 64 36
FAQ
Q1: Views는?
A: 지연 평가 범위.
Q2: 지연 평가?
A: 순회 시 계산.
Q3: 복사?
A: 안 함. 참조.
Q4: 파이프라인?
A: | 연산자로 조합.
Q5: 성능?
A:
- 복사 없음
- 지연 평가
- 순서 중요
Q6: 학습 리소스는?
A:
- “C++20 Ranges”
- “C++20 The Complete Guide”
- cppreference.com
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ Ranges | “범위 라이브러리” 가이드
- C++ Ranges | “함수형 프로그래밍” C++20 가이드
- C++ subrange | “부분 범위” 가이드
관련 글
- C++ Ranges 파이프라인·뷰 |
- C++ Ranges 기본 개념 |
- C++ Generator 완벽 가이드 | co_yield로 lazy 시퀀스·무한 수열·파이프라인 만들기
- C++20 Ranges | begin/end 반복 탈출하고 ranges 알고리즘 쓰기
- C++ Ranges Views와 파이프라인 | 지연 연산으로 효율적으로 다루기 [#25-2]