最終更新日時(UTC):
が更新

履歴 編集

customization point object
<compare>

std::partial_order(C++20)

namespace std {
  inline namespace /*unspecified*/ {

    inline constexpr /*unspecified*/ partial_order = /*unspecified*/;
  }
}

概要

partial_orderは2つの引数を受け取り、それらを半順序の上で比較する関数オブジェクトである。

効果

partial_order(a, b)のように呼び出された時、以下のいずれかと等価(上から順に考慮される)

  1. decayを通したa, bの型が異なる場合、呼び出しは不適格(コンパイルエラー)

  2. std::partial_order(本関数オブジェクト)の宣言を含まないコンテキストで、partial_ordering(partial_order(a, b))が呼び出し可能ならばpartial_ordering(partial_order(a, b))

  3. partial_ordering(a <=> b)が呼び出し可能ならばpartial_ordering(a <=> b)

  4. partial_ordering(weak_order(a, b))が呼び出し可能ならばpartial_ordering(weak_order(a, b))

  5. それ以外の場合、呼び出しは不適格

戻り値

呼び出しが適格ならば、比較結果を表すpartial_orderingの値。

例外

上記「効果」節のそれぞれのケース毎に

  1. --
  2. 呼び出されるpartial_order(a, b)およびその戻り値のpartial_orderingへの変換が例外を送出するかに従う。
  3. 呼び出されるa <=> bおよびその戻り値のpartial_orderingへの変換が例外を送出するかに従う。
  4. 呼び出されるweak_order(a, b)およびその戻り値のpartial_orderingへの変換が例外を送出するかに従う。

定数式に評価される条件

上記「効果」節のそれぞれのケース毎に

  1. --
  2. 呼び出されるpartial_order(a, b)およびその戻り値のpartial_orderingへの変換が定数評価可能であるかに従う。
  3. 呼び出されるa <=> bおよびその戻り値のpartial_orderingへの変換が定数評価可能であるかに従う。
  4. 呼び出されるweak_order(a, b)およびその戻り値のpartial_orderingへの変換が定数評価可能であるかに従う。

カスタマイゼーションポイント

上記「効果」節2,3,4のケースでは、ユーザー定義partial_order()<=>演算子を定義、もしくはweak_order()へアダプトしておくことによって実行される比較をカスタマイズすることができる。

  1. --
  2. 引数a, bの型Tと同じ名前空間、もしくはTの定義内でfriend関数としてpartial_order()を定義しておく。
  3. 引数a, bの型Tに対して、使用可能な<=>演算子を定義しておく。
  4. 引数a, bの型Tweak_orderにアダプトしておく。

ただし、どのケースにおいてもその戻り値型はpartial_orderingに変換可能でなければならない。

#include <iostream>
#include <compare>
#include <limits>

struct no_spaceship {
  int n1 = 0;
  int n2 = 0;
  int n3 = 0;

  friend auto partial_order(const no_spaceship& lhs, const no_spaceship& rhs) -> std::partial_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::partial_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. ユーザー定義weak_order()によるカスタム比較
  no_spaceship s1 = {1, 2, 3}, s2 = {2, 1, 3};
  std::cout << (std::partial_order(s1, s2) < 0) << std::endl;

  std::cout << "\n";

  //3. 浮動小数点数の比較
  constexpr auto qnan = std::numeric_limits<double>::quiet_NaN();

  std::cout << (std::partial_order(-0.0, +0.0) == 0) << std::endl;
  constexpr auto cmp = std::partial_order(-qnan, +qnan);
  std::cout << (cmp <  0) << std::endl;
  std::cout << (cmp >  0) << std::endl;
  std::cout << (cmp == 0) << std::endl;

  std::cout << "\n";

  //4. ユーザー定義<=>によるカスタム比較
  have_spaceship s3 = {1, 2, 3}, s4 = {2, 1, 3};
  std::cout << (std::partial_order(s3, s4) < 0) << std::endl;

  std::cout << "\n";

  //4. 組み込み型の比較
  std::cout << (std::partial_order(1, 2) < 0) << std::endl;
}

出力

true

true
false
false
false

false

true

バージョン

言語

  • C++20

処理系

関連項目

参照