프로그래밍/C,C++

[Modern C++20] 삼중 비교 연산자(Three-Way Comparison)

GONII 2025. 3. 28. 14:35

🔹 C++20 삼중 비교 연산자 (Three-Way Comparison, <=>)

1. 삼중 비교 연산자 (<=>)란?

C++20에서는 새로운 삼중 비교 연산자(Three-Way Comparison Operator) 인 <=> (일명 "우주선 연산자"라고도 불림)가 도입되었습니다.
이 연산자는 두 값을 비교하고 순서를 결정하는 통합 연산자로, 기존 ==, <, >, <=, >= 연산자를 하나로 통합하는 역할을 합니다.

📌 기본 문법:

a <=> b;  // a와 b를 비교하여 결과 반환

✔ a가 b보다 작으면 음수 값 반환
✔ a가 b와 같으면 0 반환
✔ a가 b보다 크면 양수 값 반환

📌 반환 타입:
<=> 연산자의 반환값은 비교 대상에 따라 다를 수 있으며, 대표적인 타입은 다음과 같습니다.

  • std::strong_ordering (강한 순서 비교)
  • std::weak_ordering (약한 순서 비교)
  • std::partial_ordering (부분 순서 비교)

2. 기본 예제

#include <iostream>
#include <compare>  // 비교 연산자를 사용하려면 필요

int main() {
    int a = 10, b = 20;

    auto result = a <=> b;

    if (result < 0)
        std::cout << "a is less than b\n";
    else if (result > 0)
        std::cout << "a is greater than b\n";
    else
        std::cout << "a is equal to b\n";
}

설명:

  • a <=> b는 std::strong_ordering 타입을 반환.
  • 비교 결과가 음수이면 a < b, 0이면 a == b, 양수이면 a > b.

3. std::strong_ordering, std::weak_ordering, std::partial_ordering 차이

C++20에서는 세 가지 비교 결과 타입이 있습니다.

타입 의미 예시

std::strong_ordering 완전한 정렬 가능 (강한 비교) 정수, 문자열
std::weak_ordering 동등하지만 완전한 비교는 불가능 (약한 비교) 일부 사용자 정의 타입
std::partial_ordering 비교할 수 없는 경우가 존재 (부분 비교) 부동소수점 (NaN 비교)

📌 예제: std::partial_ordering (부동소수점 비교)

#include <iostream>
#include <compare>

int main() {
    double x = 0.0, y = std::nan("");

    if ((x <=> y) == std::partial_ordering::unordered)
        std::cout << "x and y are unordered (NaN detected)\n";
}

설명:

  • NaN 값과의 비교는 정의되지 않음 (unordered).
  • std::partial_ordering::unordered 상태를 반환.

4. 삼중 비교 연산자와 사용자 정의 타입 (operator<=> 오버로딩)

삼중 비교 연산자는 사용자 정의 클래스에서도 사용할 수 있습니다.

#include <iostream>
#include <compare>

struct Point {
    int x, y;

    auto operator<=>(const Point& other) const = default; // 자동 비교 지원
};

int main() {
    Point p1{1, 2}, p2{2, 3};

    if (p1 < p2) 
        std::cout << "p1 is less than p2\n";
}

설명:

  • operator<=>에 = default를 사용하면 자동 비교 연산 지원.
  • 멤버 변수를 사전순 비교 (lexicographical comparison) 하여 정렬 기준 결정.
  • p1 < p2는 p1.x < p2.x 또는 p1.y < p2.y에 따라 자동 비교.

📌 수동으로 operator<=>를 정의하면 더 세부적인 비교 가능

struct Point {
    int x, y;

    auto operator<=>(const Point& other) const {
        if (auto cmp = x <=> other.x; cmp != 0)
            return cmp;
        return y <=> other.y;
    }
};

설명:

  • x 좌표를 먼저 비교하고, 같다면 y 좌표 비교.
  • cmp != 0이면 x 비교 결과 반환, 아니면 y 비교 결과 반환.

5. 기존 비교 연산자와 조합 (==, <, >, <=, >=)

삼중 비교 연산자는 자동으로 기존 비교 연산자와 함께 사용할 수 있음.

#include <iostream>
#include <compare>

struct Value {
    int val;
    auto operator<=>(const Value&) const = default; // 자동 비교 지원
};

int main() {
    Value v1{5}, v2{10};

    std::cout << std::boolalpha;
    std::cout << (v1 < v2) << std::endl;  // true
    std::cout << (v1 == v2) << std::endl; // false
}

설명:

  • <=> 연산자만 정의해도 <, >, <=, >=, ==, != 자동 지원.

6. default vs. 직접 구현

📌 자동 비교 (= default)

struct Data {
    int a, b;
    auto operator<=>(const Data&) const = default;
};

모든 멤버 변수를 순차적으로 비교
간단한 클래스에 적합
일반적으로 사용 가능

📌 사용자 정의 비교

struct Data {
    int a, b;

    auto operator<=>(const Data& other) const {
        return a <=> other.a; // b는 비교하지 않음
    }
};

특정 멤버만 비교 가능
커스텀 정렬 기준 적용 가능
복잡한 비교 로직 구현 가능


🔥 정리

C++20 <=> 삼중 비교 연산자는 두 개의 값을 비교하고 결과를 반환.
자동으로 기존 비교 연산자 (==, <, >, <=, >=) 지원.
반환 타입에 따라 std::strong_ordering, std::weak_ordering, std::partial_ordering 사용.
사용자 정의 클래스에서도 operator<=>를 쉽게 오버로딩 가능.
= default를 사용하면 자동으로 멤버 변수를 비교.

🚀 C++20에서 비교 연산을 더 쉽게, 더 강력하게! 🚀

반응형

'프로그래밍 > C,C++' 카테고리의 다른 글

[Modern C++20] concept  (0) 2025.04.08
[Modern C++] string_view  (0) 2025.04.02
[Modern C++] 람다 표현식 (Lambda Expression)  (0) 2025.03.26
[Modern C++] decltype  (0) 2025.03.25
[Modern C++] STL 자료구조  (0) 2025.03.24