std::conjunction
| ヘッダ <type_traits> で定義 |
||
| template< class... B > struct conjunction; |
(C++17以降) | |
型特性 B... の論理積を形成し、特性のシーケンスに対して論理ANDを効率的に実行します。
特殊化 std::conjunction<B1, ..., BN> は、以下のいずれかである公開かつ曖昧さのない基底を持ちます。
- sizeof...(B) == 0 の場合、std::true_type。それ以外の場合、
- bool(Bi::value) == false となる
B1, ..., BNの最初の型Bi、またはそのような型がない場合はBN。
基底クラスのメンバー名(conjunction および operator= を除く)は隠蔽されず、conjunction で曖昧さなく利用できます。
conjunction はショートサーキット評価されます。もし bool(Bi::value) == false となるテンプレート型引数 Bi が存在する場合、conjunction<B1, ..., BN>::value のインスタンス化は j > i の Bj::value のインスタンス化を必要としません。
プログラムが std::conjunction または std::conjunction_v の特殊化を追加した場合、動作は未定義です。
目次 |
[編集] テンプレートパラメータ
| B... | - | Bi::value がインスタンス化されるすべてのテンプレート引数 Bi は、基底クラスとして使用可能であり、bool に変換可能なメンバー value を定義している必要があります。 |
[編集] ヘルパー変数テンプレート
| template< class... B > constexpr bool conjunction_v = conjunction<B...>::value; |
(C++17以降) | |
[編集] 可能な実装
template<class...> struct conjunction : std::true_type {}; template<class B1> struct conjunction<B1> : B1 {}; template<class B1, class... Bn> struct conjunction<B1, Bn...> : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {}; |
[編集] 備考
conjunction の特殊化は、必ずしも std::true_type または std::false_type から継承するわけではありません。それは、bool に明示的に変換された ::value が false となる最初の B から継承するか、すべてが true に変換される場合は最後の B から継承するだけです。例えば、std::conjunction<std::integral_constant<int, 2>, std::integral_constant<int, 4>>::value は 4 です。
ショートサーキットによるインスタンス化は、conjunction を畳み込み式と区別します。(... && Bs::value) のような畳み込み式は Bs のすべての B をインスタンス化しますが、std::conjunction_v<Bs...> は値が決定できるとすぐにインスタンス化を停止します。これは、後の型がインスタンス化にコストがかかる場合や、間違った型でインスタンス化された場合にハードエラーを引き起こす可能性がある場合に特に役立ちます。
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_logical_traits |
201510L |
(C++17) | 論理演算子型特性 |
[編集] 例
#include <iostream> #include <type_traits> // func is enabled if all Ts... have the same type as T template<typename T, typename... Ts> std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>> func(T, Ts...) { std::cout << "All types in pack are the same.\n"; } // otherwise template<typename T, typename... Ts> std::enable_if_t<!std::conjunction_v<std::is_same<T, Ts>...>> func(T, Ts...) { std::cout << "Not all types in pack are the same.\n"; } template<typename T, typename... Ts> constexpr bool all_types_are_same = std::conjunction_v<std::is_same<T, Ts>...>; static_assert(all_types_are_same<int, int, int>); static_assert(not all_types_are_same<int, int&, int>); int main() { func(1, 2, 3); func(1, 2, "hello!"); }
出力
All types in pack are the same. Not all types in pack are the same.
[編集] 関連項目
| (C++17) |
論理NOTメタ関数 (クラステンプレート) |
| (C++17) |
可変長論理ORメタ関数 (クラステンプレート) |