【一人 C++20 Advent Calendar 2019】<=> 演算子が追加される【18日目】

一人 C++20 Advent Calendar 2019 18日目の記事になります。

<=> 演算子が追加

C++20 では新しく三方比較演算子(<=>) が追加されます。
宇宙船演算子とも言われてるやつですね。
<=> 演算子

  • 自分と等しい
  • 自分よりも大きい
  • 自分よりも小さい

の 3つの状態を返すための演算子で比較演算子で使用されることを想定しています。
実際に使うと以下のようになります。

#include <compare>
#include <iostream>

struct X{
    // int 型の <=> は strong_ordering というオブジェクトを返す
    // これは 0 と比較する事で
    // 等しい
    // より大きい
    // より小さい
    // を表現することができる
    std::strong_ordering
    operator <=>(X const& other) const {
        return value <=> other.value;
    }
    // = default で定義することもできる
    // この場合は == 演算子も使用することができる
    // auto operator <=>(X const& other) const = default;

    int value;
};

int
main(){
    constexpr auto x1 = X{1};
    constexpr auto x2 = X{2};
    
    std::cout << std::boolalpha;

    // 等しければ == 0 となる
    std::cout << ((x1 <=> x1) == 0) << std::endl;
    // 左辺の方が大きければ > 0 となる(正の値)
    std::cout << ((x2 <=> x1) > 0) << std::endl;
    // 左辺の方が小さければ < 0 となる(負の値)
    std::cout << ((x1 <=> x2) < 0) << std::endl;

    std::cout << "---" << std::endl;

    std::cout << (x1 < x2) << std::endl;
    std::cout << (x2 > x1) << std::endl;

    // エラー
    // 自前で <=> の処理を定義した場合は == 演算子は使用できない
    // = default で <=> を定義した場合は == 演算子を使用できる
    std::cout << (x1 == x2) << std::endl;

    return 0;
}

実際に書いてみて気になったポイントとしては、

  • <=> 演算子std::strong_ordering という専用のクラスを返す
  • 自前で <=> 演算子を定義した場合は == 演算子で比較できない
    • <=>= default で定義した場合では == 演算子で比較できる

この 2点になります。
Ruby とかだと <=>0 1 -1 みたいな数値を返すんですが、C++<=>std::strong_ordering といった専用のオブジェクトを返します。
これは 0 と比較することで

  • 等しい
  • より大きい
  • より小さい

という状態を調べることができます。
また、 <=> 演算子= default で定義したときのみ == 演算子で比較することができます。
= default を使用した場合は各メンバ変数を <=> で比較した値を返します。
<=> 演算子は結構クセが強そうですが、定義しておくことで他の比較演算子を暗黙的に使用することができるようになるのは便利ですね。

参照