Three-way comparison : c++20

struct Point {
    int x;
    int y;
    auto operator<=>(const Point& other) const {
        if (x < other.x) return -1;
        if (x > other.x) return 1;
        if (y < other.y) return -1;
        if (y > other.y) return 1;
        return 0;
    }
};
https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison
  • <=> 3방향 비교 연산자

Three-way comparison

The three-way comparison operator expressions have the form

lhs <=> rhs

The expression returns an object such that

  • (a <=> b) < 0 if lhs < rhs
  • (a <=> b) > 0 if lhs > rhs
  • (a <=> b) == 0 if lhs and rhs are equal/equivalent.

If one of the operands is of type bool and the other is not, the program is ill-formed.

If both operands have arithmetic types, or if one operand has unscoped enumeration type and the other has integral type, the usual arithmetic conversions are applied to the operands, and then

  • If a narrowing conversion is required, other than from an integral type to a floating point type, the program is ill-formed.
  • Otherwise, if the operands have integral type, the operator yields a prvalue of type std::strong_ordering:
  • std::strong_ordering::equal if both operands are arithmetically equal,
  • std::strong_ordering::less if the first operand is arithmetically less than the second
  • std::strong_ordering::greater otherwise.
  • Otherwise, the operands have floating-point type, and the operator yields a prvalue of type std::partial_ordering. The expression a <=> b yields
  • std::partial_ordering::less if a is less than b
  • std::partial_ordering::greater if a is greater than b
  • std::partial_ordering::equivalent if a is equivalent to b (-0 <=> +0 is equivalent)
  • std::partial_ordering::unordered (NaN <=> anything is unordered)

If both operands have the same enumeration type E, the operator yields the result of converting the operands to the underlying type of E and applying <=> to the converted operands.

If at least one of the operands is a pointer or pointer-to-member, array-to-pointer conversions, derived-to-base pointer conversions, function pointer conversions, and qualification conversions are applied as necessary to convert both operands to the same pointer type, and the resulting pointer type is an object pointer type, p <=> q returns a prvalue of type std::strong_ordering:

  • std::strong_ordering::equal if p == q
  • std::strong_ordering::less if p < q
  • std::strong_ordering::greater if p > q.
  • unspecified result if comparison is unspecified for these pointer values (such as when they do not point into the same object or array)

Otherwise, the program is ill-formed.

In overload resolution against user-defined operators, for pointer or enumeration type T, the following function signature participates in overload resolution:

R operator<=>(T, T);

Where R is the ordering category type defined above.

Example

Run this code

#include <compare>
#include <iostream>
 
int main() {
    double foo = -0.0;
    double bar = 0.0;
 
    auto res = foo <=> bar;
 
    if (res < 0)
        std::cout << "-0 is less than 0";
    else if (res == 0)
        std::cout << "-0 and 0 are equal";
    else if (res > 0)
        std::cout << "-0 is greater than 0";
}

Output:

-0 and 0 are equal

Notes

Three-way comparison can be automatically generated for class types, see default comparisons.

If both of the operands are arrays, three-way comparison is ill-formed.

unsigned int i = 1;
auto r = -1 < i; // existing pitfall: returns ‘false’
auto r2 = -1 <=> i; // Error: narrowing conversion required

나중에 정리해둘 내용
– 주요한 내용은 이중에서 string_ordering / weak_ordering / partial_ordering


댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다