最終更新:2026-10-12
C++20 三方比較演算子 <=>¶
3種類の順序¶
三方比較演算子<=>はスペースシップ演算子とも呼ばれ、戻り値には3種類の順序があります。ここでは gcc のソースコードの観点から深く掘り下げます。
注:お手軽版として、本節のサンプルは星球(ナレッジプラネット)に更新してあります。
使い方:<=>
#include <compare>
#include <iostream>
int main() {
auto c1 = 1.1 <=> 2.2;
auto c2 = -1 <=> 1;
std::cout << typeid(c1).name() << std::endl;
std::cout << typeid(c2).name() << std::endl;
}
出力:
1.1 <=> 2.2:これは2つの浮動小数点数を比較します。浮動小数点数に対して、標準ライブラリはstd::partial_orderingを返します。浮動小数点数には NaN が存在するため、それらの間の比較は厳密な全順序ではないからです。std::partial_orderingは結果が<、>、==またはunorderedであることを許します。
gcc のコードの静的変数を使って、partial_ordering が小于、大于、等于、无序のどれなのかを確認できます:
static const partial_ordering less;
static const partial_ordering equivalent;
static const partial_ordering greater;
static const partial_ordering unordered;
強制変換するとエラーになります:
comp.cc:6:36: error: conversion from 'std::partial_ordering' to non-scalar type 'std::strong_ordering' requested
6 | std::strong_ordering c1 = 1.1 <=> 2.2;
2. `-1 <=> 1`:これは2つの整数を比較します。整数に対して、標準ライブラリは`std::strong_ordering`を返します。整数の比較は厳密な全順序関係で、不確定なケースがないためです。`std::strong_ordering`は`<`、`>`または`==`だけを返します。
同様に、以下の4つの静的メンバを使えます。
static const strong_ordering less;
static const strong_ordering equal;
static const strong_ordering equivalent;
static const strong_ordering greater;
したがって、c1の型はstd::partial_ordering、c2の型はstd::strong_orderingです。これが、出力される型が異なる理由の説明にもなっています。
partial_ordering、strong_ordering の他に、<=>は weak_ordering を返すこともあります。静的メンバは以下の通りです:
static const weak_ordering less;
static const weak_ordering equivalent;
static const weak_ordering greater;
equal と equivalent¶
上の3種類の ordering では、等しいことを表すものが2つあることがわかります:equal と equivalent です。この2つにはどんな違いがあるのでしょうか?
ここは cppreference を直接見ると、両者に違いはありません。しかし、std::strong_ordering は等しさ(equal)を定義する唯一のカテゴリです。他のすべてのカテゴリは同値(equivalent)だけを定義します。上の静的メンバともちょうど一致しており、strong_ordering には2つあり、他には equivalent しかありません。
比較が比較対象の項目間で**強い順序**を生じる場合、同値と等値は同じです。2つの言葉で表されるのは、他のタイプの順序では同じではないからです。弱い**順序と**部分的な**順序にはそもそも**等しさ(equality)がなく、同値性(equivalence)だけを提供します。
同値とは、2つのオブジェクトが比較して等しいとみなせることを意味します。等値はさらに強いものを意味します。すなわち、比較して等しい場合、const として使われるどんな場面でも一方を他方と置き換えられます:a == b が真である限り、f(a) == f(b) という性質が真になります。ここで f は、引数の公開された const メンバを通じてアクセスできる比較顕著な状態だけを読む関数を表します。型の比較が等値を許す場合(これは強い順序の要件です)、それは同値も許します。したがって、強い順序の比較では両者は同じです。
https://en.cppreference.com/w/cpp/utility/compare/strong_ordering
なぜ三方比較演算子を使うのか?¶
三方比較演算子(<=>)を使うと、1回の操作で2つの値の順序関係を確定できますが、従来の比較演算子では複数回の比較が必要です。
従来の比較演算子の制限:
a == bが偽のとき、a < bなのかa > bなのかはわかりません。a != bが真のとき、a < bなのかa > bなのかはわかりません。a < bが偽のとき、a == bなのかa > bなのかはわかりません。a > bが偽のとき、a == bなのかa < bなのかはわかりません。a <= bが真のとき、a == bなのかa < bなのかはわかりません。a >= bが真のとき、a == bなのかa > bなのかはわかりません。
これらの制限が示すように、従来の比較演算子では2つの値の完全な関係を一度に確定できず、完全な結果を得るには複数回の比較が必要です。
本節終わり
関連トピック¶
- C++20 コルーチン入門 | C++那些事
- C++20 channel 実践 | C++那些事
- C++20 Concepts コンセプト | C++那些事
- C++20 constexpr とカンマ式 | C++那些事
- C++20 バイトオーダー endian | C++那些事
- C++20 Lambda 式(前編) | C++那些事
- C++20 モジュール Modules | C++那些事
- C++20 Ranges ライブラリ | C++那些事
- C++20 std::span の設計と落とし穴 | C++那些事
- C++20 新機能ガイド | C++那些事