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

履歴 編集

concept
<concepts>

std::boolean-testable(C++20)

namespace std {
  template<class T>
  concept boolean-testable = /*see below*/; // 説明専用コンセプト
}

概要

boolean-testableは、任意の型Tboolとして扱う事ができることを表すコンセプトである。

このコンセプトはほかのコンセプトの定義および説明に使用される説明専用のものであり、実際に使用可能ではない。

要件

まず、説明専用のboolean-testable-implコンセプトを以下の様に定義する。

template<class T>
concept boolean-testable-impl = convertible_to<T, bool>;

これを用いて、boolean-testableは以下の様に定義される。

template<class T>
concept boolean-testable =
  boolean-testable-impl<T> && requires (T&& t) {
    { !std::forward<T>(t) } -> boolean-testable-impl;
  };

モデル

  • decltype((e))Tとなる式eについて、次の条件を満たす場合に限って型Tboolean-testable-implのモデルである。
    • 次のどちらかを満たす
      • remove_cvref_t<T>はクラス型ではない
      • operator||, operator&&remove_cvref_t<T>のクラススコープで名前解決したかの様に探索した結果、候補関数は見つからない
    • operator||, operator&&ADLによる探索では不適格な宣言は見つからない
      • TADL探索範囲にTが左右どちらのオペランドになったとしても、受け入れ可能にオーバーロードされたoperator||, operator&&演算子は存在しない

2番目の条件の不適格な宣言が見つからないとは、boolean-testable-implのモデルとなる型T1, T2については、declval<T1>() && declval<T2>()およびdeclval<T1>() || declval<T2>()operator||, operator&&は確実に組み込みの演算子が使用される、と言う事を要求している。

  • decltype((e))Tとなる式eについて、次の条件を満たす場合に限って型Tboolean-testableのモデルである。
    • bool(e) == !bool(!e)

備考

boolean-testableコンセプトのモデルとなる型には、bool, std::true_type, int*等ポインタ型、std::bitset<N>::reference等がある。

booleanコンセプト

boolean-testableコンセプトは当初、真理値型を表す説明専用ではないbooleanコンセプトとして以下の様に定義されていた。

namespace std {
  template<class B>
  concept boolean =
    movable<remove_cvref_t<B>> &&
    requires(const remove_reference_t<B>& b1,
             const remove_reference_t<B>& b2, const bool a) {
      { b1 } -> convertible_to<bool>;
      { !b1 } -> convertible_to<bool>;
      { b1 && b2 } -> same_as<bool>;
      { b1 &&  a } -> same_as<bool>;
      {  a && b2 } -> same_as<bool>;
      { b1 || b2 } -> same_as<bool>;
      { b1 ||  a } -> same_as<bool>;
      {  a || b2 } -> same_as<bool>;
      { b1 == b2 } -> convertible_to<bool>;
      { b1 ==  a } -> convertible_to<bool>;
      {  a == b2 } -> convertible_to<bool>;
      { b1 != b2 } -> convertible_to<bool>;
      { b1 !=  a } -> convertible_to<bool>;
      {  a != b2 } -> convertible_to<bool>;
    };
}

このbooleanコンセプトは14個の制約式によって定義されている。これらは真理値式をなるべく正しく表現するために議論の経過と共に追加されていったものだが、これによって以下の様な問題が発生していた。

  • ある型がbooleanコンセプトを満たしているのかがわかりにくい
    • 特に、演算子オーバーロードされていると追いかけるのは非常に困難になる
  • 制約式の数が多すぎるため、少し使用しただけでコンパイル時間を増大させる
    • 例えば当初のtotally_ordered_withは直接的に8個、間接的に50個のbooleanコンセプトのチェックを要求する。totally_ordered_with1度の使用あたりbooleanのチェックだけで最悪812個の制約式のチェックを行う事になる。
  • このbooleanを正しく使用するためには、本来必要ない箇所で明示的なboolへの変換を行う必要がある。しかし、どこで必要になってどこなら必要ないのかが非常に分かりづらい。

これらの問題(共通するのは、制約式が多すぎると言う問題)によって、booleanコンセプトは検証するのも使用するのも教育するのも困難なものになってしまったため、削除される事となった。
ただ、booleanコンセプトは標準ライブラリのその他のコンセプトの定義のために使用されていたため、「標準ライブラリが必要とするときに(暗黙的に)bool型への変換が可能」と言う最低限の性質を表明し、なおかつ説明専用のboolean-testableコンセプトへと置換された。

上記定義のbooleanコンセプトはポインタ型等boolに変換可能なだけの型では満たす事はできなかったが、boolean-testableコンセプトではboolに変換可能なだけの型でも満たす事ができる。

バージョン

言語

  • C++20

関連項目

参照