namespace std {
inline namespace /*unspecified*/ {
inline constexpr /*unspecified*/ strong_order = /*unspecified*/;
}
}
概要
strong_order
は2つの引数を受け取り、それらを全順序の上で比較する関数オブジェクトである。
効果
strong_order(a, b)
のように呼び出された時、以下のいずれかと等価(上から順に考慮される)
-
std::strong_order
(本関数オブジェクト)の宣言を含まないコンテキストで、strong_ordering(strong_order(a, b))
が呼び出し可能ならばstrong_ordering(strong_order(a, b))
-
decay
を通したa, b
の型T
が浮動小数点型の場合、T
の組み込みの比較演算子による順序と一貫するstrong_ordering
の値を返す。
さらに、numeric_limits<T>::is_iec559== true
の場合、その順序はISO/IEC/IEEE 60559のtotalOrder
による全順序と一致する。 -
strong_ordering(a <=> b)
が呼び出し可能ならばstrong_ordering(a <=> b)
-
それ以外の場合、呼び出しは不適格。
戻り値
呼び出しが適格ならば、比較結果を表すstrong_ordering
の値。
例外
上記「効果」節のそれぞれのケース毎に
- --
- 呼び出される
strong_order(a, b)
およびその戻り値のstrong_ordering
への変換が例外を送出するかに従う。 - 投げない。
- 呼び出される
a <=> b
およびその戻り値のstrong_ordering
への変換が例外を送出するかに従う。
定数式に評価される条件
上記「効果」節のそれぞれのケース毎に
- --
- 呼び出される
strong_order(a, b)
およびその戻り値のstrong_ordering
への変換が定数評価可能であるかに従う。 - 引数
a, b
が定数(式)ならば、常に定数評価可能 - 呼び出される
a <=> b
およびその戻り値のstrong_ordering
への変換が定数評価可能であるかに従う。
カスタマイゼーションポイント
上記「効果」節2,4のケースでは、ユーザー定義のstrong_order()
もしくは<=>
演算子を定義しておくことによって実行される比較をカスタマイズすることができる。
- --
- 引数
a, b
の型T
と同じ名前空間、もしくはT
の定義内でfriend
関数としてstrong_order()
を定義しておく。 - --
- 引数
a, b
の型T
に対して、使用可能な<=>
演算子を定義しておく。
ただし、どちらのケースもその戻り値型はstrong_ordering
に変換可能でなければならない。
備考
ISO/IEC/IEEE 60559のtotalOrder
による全順序では、±0
や内部表現の異なるNaN
を区別した上で順序付けされる。すなわち、本関数オブジェクトによる浮動小数点数の比較においてはこれらの値を識別することができる。
その順序付けは以下のようになる。
{負のquiet NaN} <
{負のsignaling NaN} <
{負の数} < -0.0 < +0.0 <
{正の数} <
{正のsignaling NaN} <
{正のquiet NaN}
それぞれの種類のNaN
の集合内では、NaN
のペイロード(先頭ビットを除いた仮数部)の表現によって順序付けされる。
例
#include <iostream>
#include <compare>
#include <limits>
struct no_spaceship {
int n1 = 0;
int n2 = 0;
int n3 = 0;
friend auto strong_order(const no_spaceship& lhs, const no_spaceship& rhs) -> std::strong_ordering {
//1 -> 3 -> 2の順で比較
if (auto cmp = lhs.n1 <=> rhs.n1; cmp != 0) return cmp;
if (auto cmp = lhs.n3 <=> rhs.n3; cmp != 0) return cmp;
return lhs.n2 <=> rhs.n2;
}
};
struct have_spaceship {
int n1 = 0;
int n2 = 0;
int n3 = 0;
friend auto operator<=>(const have_spaceship& lhs, const have_spaceship& rhs) -> std::strong_ordering {
//宣言と逆順で比較
if (auto cmp = lhs.n3 <=> rhs.n3; cmp != 0) return cmp;
if (auto cmp = lhs.n2 <=> rhs.n2; cmp != 0) return cmp;
return lhs.n1 <=> rhs.n1;
}
};
int main()
{
std::cout << std::boolalpha;
//2. ユーザー定義strong_order()によるカスタム比較
no_spaceship s1 = {1, 2, 3}, s2 = {2, 1, 3};
std::cout << (std::strong_order(s1, s2) < 0) << std::endl;
std::cout << "\n";
//3. 浮動小数点数の比較
constexpr auto qnan = std::numeric_limits<double>::quiet_NaN();
constexpr auto snan = std::numeric_limits<double>::signaling_NaN();
std::cout << (std::strong_order(-0.0, +0.0) < 0) << std::endl;
std::cout << (std::strong_order(-qnan, +qnan) < 0) << std::endl;
std::cout << (std::strong_order(+snan, +qnan) < 0) << std::endl;
std::cout << (std::strong_order(-qnan, -snan) < 0) << std::endl;
std::cout << "\n";
//4. ユーザー定義<=>によるカスタム比較
have_spaceship s3 = {1, 2, 3}, s4 = {2, 1, 3};
std::cout << (std::strong_order(s3, s4) < 0) << std::endl;
std::cout << "\n";
//4. 組み込み型の比較
std::cout << (std::strong_order(1, 2) < 0) << std::endl;
}
xxxxxxxxxx
#include <iostream>
#include <compare>
#include <limits>
struct no_spaceship {
int n1 = 0;
int n2 = 0;
int n3 = 0;
friend auto strong_order(const no_spaceship& lhs, const no_spaceship& rhs) -> std::strong_ordering {
//1 -> 3 -> 2の順で比較
if (auto cmp = lhs.n1 <=> rhs.n1; cmp != 0) return cmp;
if (auto cmp = lhs.n3 <=> rhs.n3; cmp != 0) return cmp;
return lhs.n2 <=> rhs.n2;
}
};
struct have_spaceship {
出力
true
true
true
true
true
false
true
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1(浮動小数点数の比較が未実装) ✅
- Visual C++: ??