C++ 20 기능 소개
개념 (Concepts)
C++ 20은 C++ 11 이후 가장 큰 변화를 가져온 표준으로 평가받고 있습니다.
이 절에서는 C++ 20의 주요 기능들과 C++23에서 예정된 일부 기능들을 살펴보겠습니다.
개념은 템플릿 인자에 대한 제약 조건을 명시적으로 정의할 수 있게 해주는 기능입니다.
template<typename T>
concept ConceptName = constraint-expression;
#include <concepts>
#include <iostream>
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template<Numeric T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(5, 3) << std::endl; // OK
std::cout << add(3.14, 2.5) << std::endl; // OK
// std::cout << add("Hello", "World") << std::endl; // 컴파일 에러
return 0;
}
개념을 사용하면 템플릿 코드의 가독성이 향상되고, 컴파일 오류 메시지가 더 명확해집니다.
범위-for 루프와 초기화 구문
C++ 20에서는 범위-for 루프에 초기화 구문을 추가할 수 있게 되었습니다.
#include <iostream>
#include <vector>
int main() {
for (std::vector<int> v = {1, 2, 3, 4, 5}; const auto& elem : v) {
std::cout << elem << ' ';
}
std::cout << std::endl;
return 0;
}
모듈 (Modules)
모듈은 헤더 파일의 한계를 극복하고 컴파일 속도를 개선하기 위해 도입되었습니다.
// math.cpp
export module math;
export int add(int a, int b) {
return a + b;
}
// main.cpp
import math;
#include <iostream>
int main() {
std::cout << add(5, 3) << std::endl;
return 0;
}
모듈을 사용하면 헤더 파일의 중복 포함 문제를 해결하고, 컴파일 시간을 단축할 수 있습니다.
코루틴 (Coroutines)
코루틴은 함수의 실행을 중단하고 재개할 수 있는 기능을 제공합니다.
#include <iostream>
#include <coroutine>
struct Generator {
struct promise_type {
int current_value;
Generator get_return_object() { return Generator{this}; }
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void unhandled_exception() {}
std::suspend_always yield_value(int value) {
current_value = value;
return {};
}
};
Generator(promise_type* p) : coro(std::coroutine_handle<promise_type>::from_promise(*p)) {}
~Generator() { if (coro) coro.destroy(); }
int get_next() {
coro.resume();
return coro.promise().current_value;
}
private:
std::coroutine_handle<promise_type> coro;
};
Generator count_to(int n) {
for (int i = 1; i <= n; ++i) {
co_yield i;
}
}
int main() {
auto generator = count_to(5);
for (int i = 0; i < 5; ++i) {
std::cout << generator.get_next() << ' ';
}
std::cout << std::endl;
return 0;
}
삼중 비교 연산자 <=>
삼중 비교 연산자는 두 객체의 순서 관계를 한 번에 결정할 수 있게 해줍니다.
#include <iostream>
#include <compare>
struct Point {
int x, y;
auto operator<=>(const Point&) const = default;
};
int main() {
Point p1{1, 2}, p2{1, 3};
if (p1 < p2) {
std::cout << "p1 is less than p2" << std::endl;
} else if (p1 > p2) {
std::cout << "p1 is greater than p2" << std::endl;
} else {
std::cout << "p1 is equal to p2" << std::endl;
}
return 0;
}
constexpr 기능 확장
C++ 20에서는 constexpr의 기능이 크게 확장되어, 더 많은 코드를 컴파일 타임에 실행할 수 있게 되었습니다.
#include <vector>
#include <iostream>
constexpr std::vector<int> get_fibonacci(int n) {
std::vector<int> fib(n);
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i < n; ++i) {
fib[i] = fib[i-1] + fib[i-2];
}
return fib;
}
int main() {
constexpr auto fib = get_fibonacci(10);
for (auto n : fib) {
std::cout << n << ' ';
}
std::cout << std::endl;
return 0;
}
C++ 23 예정 기능: std::expected
C++ 23에서는 오류 처리를 위한 std::expected
클래스가 추가될 예정입니다.
#include <expected>
#include <iostream>
#include <string>
std::expected<int, std::string> safe_divide(int a, int b) {
if (b == 0) {
return std::unexpected("Division by zero");
}
return a / b;
}
int main() {
auto result = safe_divide(10, 2);
if (result) {
std::cout << "Result: " << *result << std::endl;
} else {
std::cout << "Error: " << result.error() << std::endl;
}
result = safe_divide(10, 0);
if (result) {
std::cout << "Result: " << *result << std::endl;
} else {
std::cout << "Error: " << result.error() << std::endl;
}
return 0;
}
연습 문제
Sortable
개념을 정의하고, 이를 사용하여 제네릭 버블 정렬 함수를 구현하세요. int, double, 그리고 사용자 정의 클래스에 대해 테스트하세요.- 코루틴을 사용하여 피보나치 수열을 생성하는 제너레이터를 구현하세요.
참고자료
- C++20 표준 문서
- "C++20 : The Complete Guide" by Nicolai M. Josuttis
- CppCon 발표 영상들 - C++20 관련 세션들
- C++ Reference 웹사이트의 C++20 섹션
- C++ Core Guidelines