std:: disjunction
|
ヘッダーで定義
<type_traits>
|
||
|
template
<
class
...
B
>
struct disjunction ; |
(C++17以降) | |
型特性 B... の 論理和 を形成し、特性シーケンスに対して論理OR演算を実行します。
特殊化 std :: disjunction < B1, ..., BN > は、公開かつ明確な基底クラスを持ち、それは
- sizeof... ( B ) == 0 の場合、 std:: false_type ;それ以外の場合
-
B1, ..., BNの中で bool ( Bi :: value ) == true となる最初の型Bi、またはそのような型が存在しない場合はBN
disjunction
および
operator=
を除く基底クラスのメンバー名は隠蔽されず、
disjunction
内で曖昧さなく利用可能です。
論理和は短絡評価を行います:もし
Bi
というテンプレート型引数が
bool
(
Bi
::
value
)
!
=
false
である場合、
disjunction
<
B1, ..., BN
>
::
value
のインスタンス化には
j > i
となる
Bj
::
value
のインスタンス化は必要ありません。
プログラムが
std::disjunction
または
std::disjunction_v
に対する特殊化を追加する場合、動作は未定義です。
目次 |
テンプレートパラメータ
| B... | - |
インスタンス化される全てのテンプレート引数
Bi
は基底クラスとして使用可能であり、
Bi
::
value
メンバを定義し、それが
bool
に変換可能でなければならない
|
ヘルパー変数テンプレート
|
template
<
class
...
B
>
constexpr bool disjunction_v = disjunction < B... > :: value ; |
(C++17以降) | |
実装例
template<class...> struct disjunction : std::false_type {}; template<class B1> struct disjunction<B1> : B1 {}; template<class B1, class... Bn> struct disjunction<B1, Bn...> : std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> {}; |
注記
disjunction
の特殊化は、必ずしも
std::
true_type
または
std::
false_type
から継承するわけではありません。これは単に、
::value
が
bool
に明示的に変換された際に
true
となる最初の
B
から継承するか、すべてが
false
に変換される場合は最後の
B
から継承します。例えば、
std
::
disjunction
<
std::
integral_constant
<
int
,
2
>
,
std::
integral_constant
<
int
,
4
>>
::
value
は
2
です。
短絡評価のインスタンス化は、
disjunction
を
fold expressions
と区別します:
(
...
||
Bs
::
value
)
のようなfold expressionは
Bs
内のすべての
B
をインスタンス化しますが、
std
::
disjunction_v
<
Bs...
>
は値が決定されるとインスタンス化を停止します。これは、後の型のインスタンス化が高コストである場合や、誤った型でインスタンス化された際にハードエラーを引き起こす可能性がある場合に特に有用です。
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__cpp_lib_logical_traits
|
201510L
|
(C++17) | 論理演算子型特性 |
例
#include <cstdint> #include <string> #include <type_traits> // values_equal<a, b, T>::value は a == b の場合にのみ true となります。 template<auto V1, decltype(V1) V2, typename T> struct values_equal : std::bool_constant<V1 == V2> { using type = T; }; // default_type<T>::value は常に true template<typename T> struct default_type : std::true_type { using type = T; }; // ここでdisjunctionをswitch文のように使用できます: template<int I> using int_of_size = typename std::disjunction< // values_equal<I, 1, std::int8_t>, // values_equal<I, 2, std::int16_t>, // values_equal<I, 4, std::int32_t>, // values_equal<I, 8, std::int64_t>, // default_type<void> // 最後に配置すること! >::type; static_assert(sizeof(int_of_size<1>) == 1); static_assert(sizeof(int_of_size<2>) == 2); static_assert(sizeof(int_of_size<4>) == 4); static_assert(sizeof(int_of_size<8>) == 8); static_assert(std::is_same_v<int_of_size<13>, void>); // double から Foo が構築可能かどうかのチェックはハードエラーを引き起こします struct Foo { template<class T> struct sfinae_unfriendly_check { static_assert(!std::is_same_v<T, double>); }; template<class T> Foo(T, sfinae_unfriendly_check<T> = {}); }; template<class... Ts> struct first_constructible { template<class T, class...Args> struct is_constructible_x : std::is_constructible<T, Args...> { using type = T; }; struct fallback { static constexpr bool value = true; using type = void; // 何も見つからなかった場合に返す型 }; template<class... Args> using with = typename std::disjunction<is_constructible_x<Ts, Args...>..., fallback>::type; }; // OK, is_constructible<Foo, double> はインスタンス化されない static_assert(std::is_same_v<first_constructible<std::string, int, Foo>::with<double>, int>); static_assert(std::is_same_v<first_constructible<std::string, int>::with<>, std::string>); static_assert(std::is_same_v<first_constructible<std::string, int>::with<const char*>, std::string>); static_assert(std::is_same_v<first_constructible<std::string, int>::with<void*>, void>); int main() {}
関連項目
|
(C++17)
|
論理NOTメタ関数
(クラステンプレート) |
|
(C++17)
|
可変長論理ANDメタ関数
(クラステンプレート) |