What is the <=> (“spaceship”, three-way comparison) operator in C++?

后端 未结 4 1106
鱼传尺愫
鱼传尺愫 2020-11-28 18:30

While I was trying to learn about C++ operators, I stumbled upon a strange comparison operator on cppreference.com,* in a table that looked like

4条回答
  •  萌比男神i
    2020-11-28 19:13

    Defaulting <=> automatically gives ==, !=, <, >, <=, >=

    C++20 has a new "default comparison" feature setup so that defaulting <=> gives all the others for free. I believe that this has been the major motivation behind the addition of operator<=>.

    Adapted from https://en.cppreference.com/w/cpp/language/default_comparisons:

    main.cpp

    #include 
    #include 
    #include 
    
    struct Point {
        int x;
        int y;
        auto operator<=>(const Point&) const = default;
    };
    
    int main() {
        Point pt1{1, 1}, pt2{1, 2};
    
        // Just to show it Is enough for `std::set`.
        std::set s;
        s.insert(pt1);
    
        // Do some checks.
        assert(!(pt1 == pt2));
        assert( (pt1 != pt2));
        assert( (pt1 <  pt2));
        assert( (pt1 <= pt2));
        assert(!(pt1 >  pt2));
        assert(!(pt1 >= pt2));
    }
    

    compile and run:

    sudo apt install g++-10
    g++-10 -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
    ./main.out
    

    An equivalent more explicit version of the above would be:

    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;
        }
        bool operator==(const Point& other) const = default;
    };
    

    In this case, we need to explicitly set bool operator==(const Point& other) const = default; because if operator<=> is not defaulted (e.g. as given explicitly above), then operator== is not automatically defaulted:

    Per the rules for any operator<=> overload, a defaulted <=> overload will also allow the type to be compared with <, <=, >, and >=.

    If operator<=> is defaulted and operator== is not declared at all, then operator== is implicitly defaulted.

    The above example uses the same algorithm as the default operator<=>, as explained by cppreference as:

    The default operator<=> performs lexicographical comparison by successively comparing the base (left-to-right depth-first) and then non-static member (in declaration order) subobjects of T to compute <=>, recursively expanding array members (in order of increasing subscript), and stopping early when a not-equal result is found

    Before C++20, you could not do something like operator== = default, and defining one operator would not lead to the others being defined, e.g. the following fails to compile with -std=c++17:

    #include 
    
    struct Point {
        int x;
        int y;
        auto operator==(const Point& other) const {
            return x == other.x && y == other.y;
        };
    };
    
    int main() {
        Point pt1{1, 1}, pt2{1, 2};
    
        // Do some checks.
        assert(!(pt1 == pt2));
        assert( (pt1 != pt2));
    }
    

    with error:

    main.cpp:16:18: error: no match for ‘operator!=’ (operand types are ‘Point’ and ‘Point’)
       16 |     assert( (pt1 != pt2));
          |              ~~~ ^~ ~~~
          |              |      |
          |              Point  Point
    

    The above does compile under -std=c++20 however.

    Related: Are any C++ operator overloads provided automatically based on others?

    Tested on Ubuntu 20.04, GCC 10.2.0.

提交回复
热议问题