最終更新日時:
が更新

履歴 編集

named requirement

Cpp17EqualityComparable

概要

Cpp17EqualityComparableは、型Tの値が==演算子で等値比較できることを表す要件である。

std::find()のように値を探すアルゴリズムや、std::unordered_mapのようにキーの一致を判定するコンテナが、この要件を要求する。

要件

型Tの(CV修飾された可能性のある)値a、b、cにおいて、以下の式が妥当であること。

a == b

  • 結果の型がboolean-testableのモデルであること
  • ==が同値関係であること。すなわち、以下の性質をもつこと
    • すべてのaについて、a == bがtrueとなること (反射律)
    • a == bならば、b == aとなること (対称律)
    • a == bかつb == cならば、a == cとなること (推移律)

対応する標準コンセプト

この要件との違いは以下である。

  • この要件が要求する式はa == bのみである。コンセプトはa == b・a != b・b == a・b != aの4つの式を要求する
  • この要件は==が同値関係であることを要求する。コンセプトはさらに、a == bがtrueとなるのはaとbが等値であるとき、かつそのときだけであることを要求する
    • 値の一部だけを比較する==は、同値関係ではあるが等値の判定ではないため、この要件は満たすがコンセプトのモデルとはならない
  • コンセプトはコンパイル時に検査できる

コンセプトを満たす型はこの要件も満たすが、その逆は成り立たない。

例

等値比較可能な型を実装する (最小要件を満たす実装)

要件が求める式はa == bのみであるため、等値比較演算子をひとつ定義すればよい。

#include <iostream>
#include <vector>
#include <algorithm>

// 要件が求めるのは式`a == b`が妥当であることだけなので、
// 等値比較演算子をひとつ定義すれば要件を満たす
struct ID {
  int value;

  // 反射律・対称律・推移律を満たすように実装する
  friend bool operator==(const ID& a, const ID& b)
  {
    return a.value == b.value;
  }
};

int main()
{
  std::vector<ID> ids = {{1}, {2}, {3}};

  // std::findは、要素型がCpp17EqualityComparable要件を満たすことを要求する
  auto it = std::find(ids.begin(), ids.end(), ID{2});
  std::cout << it->value << std::endl;
}

出力

2

等値比較可能な型を実装する (標準コンセプトも満たす実装)

等値比較演算子を= defaultで定義すると、全メンバの等値比較となり、std::equality_comparableも満たす。

#include <iostream>
#include <concepts>

struct Point {
  int x;
  int y;

  // = defaultで定義すると、全メンバの等値比較となる
  bool operator==(const Point&) const = default;
};

// C++20では`!=`が`==`から自動的に導出されるため、標準コンセプトも満たす
static_assert(std::equality_comparable<Point>);

int main()
{
  Point a = {1, 2};
  Point b = {3, 4};

  std::cout << std::boolalpha;
  std::cout << (a == b) << std::endl;
  std::cout << (a != b) << std::endl;
}

出力

false
true

関連項目