콘텐츠로 이동

C++20 Spaceship Operator — 3방향 비교 연산자

C++20 이전에는 <, <=, >, >=, ==, != 6개의 비교 연산자를 각각 정의해야 했습니다. <=> (three-way comparison, 우주선 연산자)를 정의하면 나머지 연산자를 컴파일러가 자동으로 생성합니다.


#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를 사용하면 멤버를 선언 순서대로 사전식 비교합니다.


타입의미예시
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 반환
}
};

멤버 중 일부만 비교에 포함하거나 순서를 바꾸고 싶을 때 직접 정의합니다.

#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;
}
};

#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;
});

// 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개 자동 생성
};

  • 부동소수점 멤버가 있으면 = defaultpartial_ordering을 반환합니다.
  • == default<=> default와 별도로 생성됩니다 — 성능 최적화를 위해 두 개를 함께 default 선언하는 것이 권장됩니다.
  • 상속 계층에서는 기반 클래스의 <=> 반환 타입과 파생 클래스의 반환 타입이 일치해야 합니다.

<=> 연산자 하나로 비교 관련 보일러플레이트를 대폭 줄일 수 있습니다. 단순한 값 타입은 = default로, 커스텀 정렬 규칙이 필요하면 직접 구현하되 반환 타입의 비교 카테고리를 신중히 선택하세요.