std::conjunction - cppreference.com
提供: cppreference.com
<tbody> </tbody>
|
|
(1) | (C++17以上) |
型特性 B... の論理積を形成します。 実質的に特性の並びに AND を行います。
特殊化 std::conjunction<B1, ..., BN> は以下のようなパブリックな曖昧でない基底を持ちます。
sizeof...(B) == 0であればstd::true_type、そうでなければB1, ..., BN内のbool(Bi::value) == falseである最初の型Bi、またはそのような型がなければBN。
conjunction と operator= 以外の基底クラスのメンバ名は隠蔽されておらず、 conjunction 内で曖昧さなく利用可能です。
論理積は短絡評価です。 bool(Bi::value) == false であるテンプレート型引数 Bi が存在する場合、 conjunction<B1, ..., BN>::value の実体化は j > i に対する Bj::value の実体化を要求しません。
テンプレート引数
| B... | - | Bi::value が実体化されるすべてのテンプレート引数 Bi は基底クラスとして使用可能でなければならず、 bool に変換可能なメンバ value を定義しなければなりません。
|
ヘルパー変数テンプレート
<tbody> </tbody>
|
|
(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 に変換されたとき false である ::value を持つ最初の 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...> はいったん値が決定されれば実体化を停止します。 これは後ろの型が実体化するのに高価であるか、間違った型で実体化したときに難しいエラーが発生する場合に、特に役に立ちます。
例
#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 T\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 T\n"; } int main() { func(1, 2, 3); func(1, 2, "hello!"); }
出力:
all types in pack are T not all types in pack are T