std::disjunction
來自 cppreference.com
定義於標頭檔案 <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 的成員 value 。 |
[編輯] 輔助變數模板
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
,或者當所有 B
都轉換為 false 時繼承自最後一個 B
。例如,std::disjunction<std::integral_constant<int, 2>, std::integral_constant<int, 4>>::value 為 2。
短路例項化將 disjunction
與摺疊表示式區分開來:像 (... || Bs::value) 這樣的摺疊表示式會例項化 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 is true if and only if a == b. template<auto V1, decltype(V1) V2, typename T> struct values_equal : std::bool_constant<V1 == V2> { using type = T; }; // default_type<T>::value is always true template<typename T> struct default_type : std::true_type { using type = T; }; // Now we can use disjunction like a switch statement: 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> // must be last! >::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>); // checking if Foo is constructible from double will cause a hard error 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; // type to return if nothing is found }; template<class... Args> using with = typename std::disjunction<is_constructible_x<Ts, Args...>..., fallback>::type; }; // OK, is_constructible<Foo, double> not instantiated 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 元函式 (類模板) |