C++20 Spaceship Operator — 3방향 비교 연산자
C++20 이전에는 <, <=, >, >=, ==, != 6개의 비교 연산자를 각각 정의해야 했습니다. <=> (three-way comparison, 우주선 연산자)를 정의하면 나머지 연산자를 컴파일러가 자동으로 생성합니다.
1. 기본 문법
섹션 제목: “1. 기본 문법”#include <compare>
struct Point { int x, y;
// <=> 하나로 ==, !=, <, <=, >, >= 전부 생성 auto operator<=>(const Point&) const = default;};
int main() { Point a{1, 2}, b{1, 3}; bool lt = (a < b); // true bool eq = (a == b); // false}= default를 사용하면 멤버를 선언 순서대로 사전식 비교합니다.
2. 비교 카테고리
섹션 제목: “2. 비교 카테고리”| 타입 | 의미 | 예시 |
|---|---|---|
std::strong_ordering | 동치는 완전히 같음 | 정수, 포인터 |
std::weak_ordering | 동치이지만 구별 가능 | 대소문자 무시 문자열 |
std::partial_ordering | 비교 불가 값 존재 | 부동소수점(NaN) |
#include <compare>#include <cmath>
struct Vec2 { double x, y;
std::partial_ordering operator<=>(const Vec2& o) const { double mag1 = std::sqrt(x*x + y*y); double mag2 = std::sqrt(o.x*o.x + o.y*o.y); return mag1 <=> mag2; // NaN 포함 시 unordered 반환 }};3. 커스텀 구현
섹션 제목: “3. 커스텀 구현”멤버 중 일부만 비교에 포함하거나 순서를 바꾸고 싶을 때 직접 정의합니다.
#include <compare>#include <string>
struct Employee { int id; std::string name; double salary;
// id만으로 비교 std::strong_ordering operator<=>(const Employee& o) const { return id <=> o.id; }
bool operator==(const Employee& o) const { return id == o.id; }};4. std::compare_three_way 활용
섹션 제목: “4. std::compare_three_way 활용”#include <compare>#include <algorithm>#include <vector>
std::vector<int> v = {5, 3, 1, 4, 2};
// <=> 기반 정렬 (오름차순)std::ranges::sort(v, [](int a, int b) { return (a <=> b) < 0;});5. 기존 코드 마이그레이션
섹션 제목: “5. 기존 코드 마이그레이션”// Before (C++17)struct Rect { int w, h; bool operator<(const Rect& o) const { return w < o.w || (w == o.w && h < o.h); } bool operator==(const Rect& o) const { return w == o.w && h == o.h; } // ... 4개 더 필요};
// After (C++20)struct Rect { int w, h; auto operator<=>(const Rect&) const = default; // 6개 자동 생성};6. 주의사항
섹션 제목: “6. 주의사항”- 부동소수점 멤버가 있으면
= default는partial_ordering을 반환합니다. == default는<=> default와 별도로 생성됩니다 — 성능 최적화를 위해 두 개를 함께default선언하는 것이 권장됩니다.- 상속 계층에서는 기반 클래스의
<=>반환 타입과 파생 클래스의 반환 타입이 일치해야 합니다.
<=> 연산자 하나로 비교 관련 보일러플레이트를 대폭 줄일 수 있습니다. 단순한 값 타입은 = default로, 커스텀 정렬 규칙이 필요하면 직접 구현하되 반환 타입의 비교 카테고리를 신중히 선택하세요.