C++/標準ライブラリ/compare
はじめに
[編集]C++20から導入された3方向比較演算子 <=> は、2つの値の大小関係を表すために使用されます。この演算子は、< > == の3つの比較結果を1つの値にまとめて返すことができます。
<compare>ヘッダーは、この3方向比較演算子と関連する機能を提供します。比較カテゴリ型、比較コンセプト、補助クラステンプレート、カスタマイゼーションポイントオブジェクト、比較関数オブジェクトなどが定義されています。
比較カテゴリ型
[編集]<compare>ヘッダーでは、3方向比較の結果を表す型として、partial_ordering、weak_ordering、strong_orderingの3つの比較カテゴリ型が定義されています。
partial_ordering
[編集]partial_orderingは、比較不可能な値を表せる最弱の比較カテゴリ型です。以下の4つの値を取ります。
less- 小なり
equivalent- 等しい
greater- 大なり
unordered- 比較不可能
weak_ordering
[編集]weak_orderingは、比較不可能な値を表せない比較カテゴリ型です。partial_orderingと同じく、less、equivalent、greaterの3つの値を取ります。
strong_ordering
[編集]strong_orderingは、最強の比較カテゴリ型です。equalとequivalentを区別でき、他の型へ変換可能です。以下の4つの値を取ります。
less- 小なり
equal- 等しい(同一オブジェクト)
equivalent- 等しい(別オブジェクト)
greater- 大なり
これらのカテゴリ型は、順序付けられており、strong_ordering -> weak_ordering -> partial_orderingの順に強さが弱くなります。比較対象の型が持つ性質に合わせて、適切なカテゴリ型を選択します。
比較コンセプト
[編集]<compare>ヘッダーでは、3方向比較の対象となる型の要件を定義するコンセプトが導入されています。
three_way_comparable
[編集]three_way_comparableコンセプトは、型Tが3方向比較可能であることを要求します。つまり、a <=> bの演算が有効で、その結果がCat型(partial_orderingがデフォルト)へ変換可能であることを求めています。また、==、!=、<、>、<=、>=の従来の比較演算子も利用可能でなければなりません。
three_way_comparable_with
[編集]three_way_comparable_withコンセプトは、型TとUが相互に3方向比較可能であることを要求します。three_way_comparableの要件に加え、t <=> uとu <=> tの両方が有効で、その結果がCat型へ変換可能でなければなりません。
これらのコンセプトを満たす型は、3方向比較や従来の比較演算子を使った処理を安全に行えます。
補助クラステンプレート
[編集]<compare>ヘッダーには、3方向比較に関連したクラステンプレートがいくつか定義されています。
common_comparison_category
[編集]common_comparison_categoryは、渡された型のリストから、もっとも強い比較カテゴリ型を導出するクラステンプレートです。たとえば、common_comparison_category<int, strong_ordering>::typeはstrong_orderingとなります。
compare_three_way_result
[編集]compare_three_way_resultは、2つの型TとUに対して、TとUの3方向比較の結果型を求めるクラステンプレートです。compare_three_way_result_tはその結果型の略記型エイリアスです。
例えば、compare_three_way_result_t<int, double>はstrong_orderingとなります。この結果型は、3方向比較の結果を受け取る変数の型として使用できます。
比較カスタマイゼーションポイントオブジェクト
[編集]<compare>ヘッダーには、3方向比較の実装をカスタマイズするためのカスタマイゼーションポイントオブジェクトが用意されています。
strong_order、weak_order、partial_order
[編集]strong_order、weak_order、partial_orderは、それぞれstrong_ordering、weak_ordering、partial_ordering型の結果を生成する3方向比較関数オブジェクトです。
これらは、対象の型に3方向比較演算子<=>が定義されていない場合に、独自の比較関数を提供することで比較をカスタマイズできます。
*_fallback版
[編集]さらに、compare_strong_order_fallback、compare_weak_order_fallback、compare_partial_order_fallbackと呼ばれる*_fallback版のオブジェクトも用意されています。
これらは、型に<=>演算子と従来の6つの比較演算子(<、>、==、!=、<=、>=)がどちらも定義されていない場合に、比較関数を提供します。
比較関数オブジェクト
[編集]<compare>ヘッダーには、3方向比較を実行する関数オブジェクトも定義されています。
compare_three_way
[編集]compare_three_wayは、2つの値の3方向比較を実行する関数オブジェクトです。結果はcompare_three_way_result_tで求められた型になります。
この関数オブジェクトは、カスタマイゼーションポイントオブジェクトを経由して呼び出されることが多く、直接使うことはあまりありません。
is_eq、is_neq、is_lt、is_lteq、is_gt、is_gteq
[編集]これらは、3方向比較の結果から、従来の比較演算子に対応する真理値を取り出すヘルパー関数です。partial_ordering型の値に対して使用できます。
補足
[編集]従来の比較演算子との関係については、<=>演算子が利用可能な型では、その結果から従来の6つの比較演算子の結果が導出されます。一方、<=>が利用できない型では、従来の演算子の結果から<=>の結果が導出されます。
効率的な3方向比較実装については、型に専用の<=>演算子を定義することで最適化できます。また、spaceshipトレイトを使ってカスタマイズすることもできます。
まとめ
[編集]<compare>ヘッダーは、C++20から導入された3方向比較演算子とそれに関連した機能を提供しています。比較カテゴリ型、比較コンセプト、補助クラステンプレート、カスタマイゼーションポイントオブジェクト、比較関数オブジェクトなどの機能が用意されており、効率的で安全な比較を実現できます。