導入
C++のクラス設計において、比較演算子(==, !=, <, <=, >, >=)をすべて実装するのは非常に手間のかかる作業です。従来のC++では、これら6つの演算子を一つずつ定義する必要があり、コードの冗長化や実装漏れによるバグの原因となっていました。C++20で導入された「三方比較演算子(<=>)」は、この課題を根本から解決します。これを使うことで、比較ロジックを最小限の記述で完結させることが可能になります。
基礎知識
三方比較演算子(<=>)は、通称「宇宙船演算子」と呼ばれます。この演算子は、2つの値を比較し、その結果を「負の値(左が小さい)」「0(等しい)」「正の値(左が大きい)」のいずれかとして返します。
この演算子の最大の特徴は、コンパイラが自動的に比較結果のカテゴリを判断し、適切な戻り値の型(std::strong_ordering, std::weak_ordering, std::partial_ordering)を生成してくれる点にあります。
実装/解決策
クラス内でデフォルトの比較を実装したい場合、以下のように記述するだけで済みます。
1. ヘッダーファイルに
2. 比較したい演算子に = default を指定する。
これにより、コンパイラはメンバ変数の宣言順に基づいて、すべての比較演算子を自動的に生成してくれます。個別にロジックを書きたい場合でも、<=> を一つ実装するだけで、他の演算子は自動的に追従して機能するようになります。
サンプルプログラム
以下のコードは、メンバ変数を比較するクラスの定義例です。
include
include
struct User {
int id;
int score;
// <=> をデフォルトで生成。これだけで ==, !=, <, >, <=, >= が全て自動生成される
auto operator<=>(const User&) const = default;
};
int main() {
User u1{1, 100};
User u2{1, 200};
// 三方比較の結果を評価
auto result = (u1 <=> u2);
if (result < 0) { std::cout << "u1はu2より小さいです。" << std::endl; } else if (result == 0) { std::cout << "u1とu2は等しいです。" << std::endl; } else { std::cout << "u1はu2より大きいです。" << std::endl; } return 0; }
応用・注意点
注意点1:メンバ変数の順序
デフォルト生成(= default)を使用する場合、比較はクラス内のメンバ変数の宣言順に行われます。意図しない順序で比較されないよう、メンバ変数の並び順には注意してください。
注意点2:浮動小数点数の比較
浮動小数点数(doubleやfloat)を扱う場合、NaN(非数)が含まれる可能性があるため、比較結果が std::partial_ordering になることがあります。この場合、単純な大小関係とは異なる挙動になる可能性があるため、厳密な比較が必要なロジックでは注意が必要です。
活用テクニック:
特定のメンバ変数のみを比較対象から外したい場合は、デフォルト生成ではなく、手動で operator<=> をオーバーロードしてください。その際、比較演算子を一つ定義するだけで、他の演算子も正しく機能するため、メンテナンス性が大幅に向上します。

コメント