2025. 2. 22. 18:16ㆍ프로그래밍 언어/C++
📌 12.4 C++20: concepts와 범위 기반 for 개선
C++20은 모던 C++에서 가장 큰 변화 중 하나로, 템플릿 타입 제약을 위한 concepts, 향상된 범위 기반 for 루프, 코루틴 및 ranges 라이브러리를 제공한다.
이를 통해 코드를 더욱 직관적이고 최적화할 수 있으며, 컴파일 타임 안정성이 향상된다.
📌 1. 템플릿에서 concepts를 활용한 타입 제약
🔹 (1) 기존 템플릿의 문제점
C++17까지는 템플릿에서 타입을 제한할 수 없어, 잘못된 타입이 들어와도 컴파일 에러 메시지가 모호했다.
💡 예제: 기존 C++17 템플릿 (제약 없음)
#include <iostream>
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(3, 5) << std::endl; // 정상 동작
std::cout << add("Hello, ", "World!"); // 컴파일 오류 (문자열 덧셈 불가)
return 0;
}
🔹 문제점
- add("Hello", "World")는 문자열 포인터(char*)를 더할 수 없어 컴파일 에러 발생.
- 에러 메시지가 모호하여 원인을 찾기 어려움.
🔹 (2) C++20 concepts를 활용한 타입 제약
C++20에서는 concepts를 도입하여, 템플릿 타입을 제약할 수 있음.
이를 통해 템플릿의 타입 검사를 컴파일 타임에 수행할 수 있으며, 가독성이 좋아짐.
💡 예제: concepts를 활용한 타입 제약
#include <iostream>
#include <concepts>
// 정수형 타입만 허용하는 개념 정의
template <typename T>
concept Numeric = std::integral<T>;
template <Numeric T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(3, 5) << std::endl; // 정상 동작
// std::cout << add(3.5, 2.1); // 컴파일 오류 (정수형만 허용)
return 0;
}
🔹 출력 결과
8
💡 설명
- concept Numeric = std::integral<T>; → std::integral을 이용해 정수형만 허용하도록 제한.
- template <Numeric T> → 템플릿에서 Numeric을 적용하여 정수형 타입만 허용.
- 컴파일 타임에 타입 검사가 수행되어, 부적절한 타입은 즉시 에러 발생.
🔹 (3) requires 절을 활용한 concepts
C++20에서는 requires를 활용하여 더 유연하게 타입 제약 가능.
💡 예제: requires를 활용한 타입 제약
#include <iostream>
#include <concepts>
template <typename T>
requires std::integral<T> // 정수 타입만 허용
T multiply(T a, T b) {
return a * b;
}
int main() {
std::cout << multiply(4, 6) << std::endl; // 정상 동작
// std::cout << multiply(2.5, 3.1); // 컴파일 오류 (정수만 허용)
return 0;
}
🔹 출력 결과
24
💡 설명
- requires std::integral<T>를 사용하여 정수 타입만 허용.
- 가독성이 높아지고, 오류 메시지가 더 명확해짐.
📌 2. 향상된 범위 기반 for 루프 사용법
🔹 (1) 기존 for 루프의 문제점
C++17까지는 범위 기반 for 루프에서 std::vector<bool>을 올바르게 순회하기 어려웠다.
💡 예제: 기존 C++17의 std::vector<bool> 문제
#include <iostream>
#include <vector>
int main() {
std::vector<bool> flags = {true, false, true};
// 오류 발생 가능 (vector<bool>은 프록시 객체를 반환)
for (bool flag : flags) {
std::cout << flag << " ";
}
return 0;
}
🔹 문제점
- std::vector<bool>은 프록시 객체(proxy object)를 반환하여, 값이 의도와 다르게 동작할 수 있음.
🔹 (2) C++20의 향상된 범위 기반 for 루프
C++20에서는 범위 기반 for 루프가 std::vector<bool>을 올바르게 처리할 수 있도록 개선되었다.
💡 예제: C++20에서 std::vector<bool>을 올바르게 처리
#include <iostream>
#include <vector>
int main() {
std::vector<bool> flags = {true, false, true};
for (bool flag : flags) { // 안전하게 순회 가능
std::cout << flag << " ";
}
return 0;
}
🔹 출력 결과
1 0 1
💡 설명
- C++20부터 std::vector<bool>도 안전하게 범위 기반 for 루프에서 사용 가능.
📌 3. 기본적인 문법 개선 (코루틴, ranges 등)
C++20에서는 코루틴(Coroutines)과 ranges 라이브러리가 추가되어 코드가 더욱 간결해졌다.
🔹 (1) 코루틴 (Coroutines) 개요
- C++20의 코루틴은 함수 실행을 중단하고 다시 시작할 수 있도록 지원.
- 비동기 프로그래밍과 효율적인 제너레이터(generator) 구현이 가능.
💡 예제: C++20 코루틴을 활용한 숫자 생성기
#include <iostream>
#include <coroutine>
struct Generator {
struct promise_type {
int current_value;
std::suspend_always yield_value(int value) {
current_value = value;
return {};
}
Generator get_return_object() { return Generator{this}; }
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
using handle_type = std::coroutine_handle<promise_type>;
handle_type handle;
Generator(promise_type* p) : handle(handle_type::from_promise(*p)) {}
~Generator() { handle.destroy(); }
bool next() {
if (!handle.done()) {
handle.resume();
return true;
}
return false;
}
int getValue() { return handle.promise().current_value; }
};
Generator counter() {
for (int i = 1; i <= 5; i++) {
co_yield i;
}
}
int main() {
auto gen = counter();
while (gen.next()) {
std::cout << gen.getValue() << " ";
}
return 0;
}
🔹 출력 결과
1 2 3 4 5
💡 설명
- co_yield를 사용하여 중간 값을 반환하고 실행을 일시 중지.
- 다음 값을 요청하면 중단된 위치에서 실행을 재개.
📌 4. 정리
개념 | 설명 |
concepts | 템플릿에서 타입을 제한하여 컴파일 타임 오류를 줄임 |
requires 절 | 특정 조건을 만족하는 타입만 템플릿에 사용할 수 있도록 제약 |
향상된 범위 기반 for | std::vector<bool>을 포함한 컨테이너를 안전하게 순회 가능 |
코루틴 | co_yield, co_await, co_return을 통해 비동기 프로그래밍 지원 |
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 초급 - 추가 내용 (심화 학습) (1 - 네임스페이스 (namespace)) (0) | 2025.02.22 |
---|---|
C++ 초급 - 12. 최신 C++ 기능 소개 (5 - C++23: std::expected 기본 개념) (0) | 2025.02.22 |
C++ 초급 - 12. 최신 C++ 기능 소개 (3 - C++17: 구조적 바인딩과 if constexpr) (0) | 2025.02.22 |
C++ 초급 - 12. 최신 C++ 기능 소개 (2 - C++14: 개선된 스마트 포인터) (0) | 2025.02.22 |
C++ 초급 - 12. 최신 C++ 기능 소개 (1 - C++11: 주요 기능 소개) (0) | 2025.02.22 |