std::disjunction
| Definiert in der Kopfdatei <type_traits> |
||
| template< class... B > struct disjunction; |
(seit C++17) | |
Bildet die logische Disjunktion der Typmerkmale B... und führt effektiv ein logisches ODER auf der Sequenz von Merkmalen aus.
Die Spezialisierung std::disjunction<B1, ..., BN> hat eine öffentliche und eindeutige Basis, die
- falls sizeof...(B) == 0, std::false_type ist; andernfalls
- der erste Typ
BiinB1, ..., BNist, für den bool(Bi::value) == true gilt, oderBN, wenn es keinen solchen Typ gibt.
Die Mitgliedsnamen der Basisklasse, mit Ausnahme von disjunction und operator=, sind nicht verborgen und in disjunction eindeutig verfügbar.
Die Disjunktion ist kurzschließend: Wenn es ein Template-Typargument Bi mit bool(Bi::value) != false gibt, erfordert das Instanziieren von disjunction<B1, ..., BN>::value nicht die Instanziierung von Bj::value für j > i.
Wenn das Programm Spezialisierungen für std::disjunction oder std::disjunction_v hinzufügt, ist das Verhalten undefiniert.
Inhalt |
[edit] Template-Parameter
| B... | - | jedes Template-Argument Bi, für das Bi::value instanziiert wird, muss als Basisklasse verwendbar sein und ein Mitglied value definieren, das in bool konvertierbar ist. |
[edit] Hilfs-Variablen-Template
| template< class... B > constexpr bool disjunction_v = disjunction<B...>::value; |
(seit C++17) | |
[edit] Mögliche Implementierung
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...>> {}; |
[edit] Hinweise
Eine Spezialisierung von disjunction erbt nicht notwendigerweise von std::true_type oder std::false_type: sie erbt einfach vom ersten B, dessen ::value, explizit in bool konvertiert, true ist, oder vom letzten B, wenn alle zu false konvertieren. Zum Beispiel ist std::disjunction<std::integral_constant<int, 2>, std::integral_constant<int, 4>>::value gleich 2.
Die Kurzschluss-Instanziierung unterscheidet disjunction von Falt-Ausdrücken: ein Falt-Ausdruck wie (... || Bs::value) instanziiert jedes B in Bs, während std::disjunction_v<Bs...> die Instanziierung stoppt, sobald der Wert bestimmt werden kann. Dies ist besonders nützlich, wenn die späteren Typen teuer zu instanziieren sind oder einen schwerwiegenden Fehler verursachen können, wenn sie mit dem falschen Typ instanziiert werden.
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_logical_traits |
201510L |
(C++17) | Typ-Traits für logische Operatoren |
[edit] Beispiel
#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() {}
[edit] Siehe auch
| (C++17) |
logische NOT-Metafunktion (Klassenvorlage) |
| (C++17) |
variadische logische AND-Metafunktion (Klassenvorlage) |