namespace std {
template<class T>
concept boolean-testable = see below; // 説明専用コンセプト
}
概要
boolean-testableは、任意の型Tをboolとして扱う事ができることを表すコンセプトである。
このコンセプトはほかのコンセプトの定義および説明に使用される説明専用のものであり、実際に使用可能ではない。
要件
まず、説明専用の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について、次の条件を満たす場合に限って型Tはboolean-testable-implのモデルである。
2番目の条件の不適格な宣言が見つからないとは、boolean-testable-implのモデルとなる型T1, T2については、declval<T1>() && declval<T2>()およびdeclval<T1>() || declval<T2>()のoperator||, operator&&は確実に組み込みの演算子が使用される、と言う事を要求している。
decltype((e))がTとなる式eについて、次の条件を満たす場合に限って型Tはboolean-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
関連項目
参照
- P0898R3 Standard Library Concepts
- P1754R1 Rename concepts to standard_case for C++20, while we still can
- LWG Issue 3208. Boolean's expression requirements are ordered inconsistently
- P1934R0
booleanConsidered Harmfulbooleanコンセプトが標準ライブラリのコンセプトとして不適格である理由について
- P1964R0 Wording for
boolean-testable - P1964R2 Wording for
boolean-testableboolean-testableコンセプトについて