Namensräume
Varianten
Aktionen

std::disjunction

Von cppreference.com
< cpp‎ | types
 
 
Metaprogrammierungsbibliothek
Typmerkmale
Typkategorien
(C++11)
(C++11)(DR*)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11) 
(C++11)
(C++11)
Typeneigenschaften
(C++11)
(C++11)
(C++14)
(C++11)(deprecated in C++26)
(C++11)(bis C++20*)
(C++11)(veraltet in C++20)
(C++11)
Typmerkmalskonstanten
Metafunktionen
disjunction
(C++17)
(C++17)
Unterstützte Operationen
Beziehungen und Eigenschaftsabfragen
Typmodifikationen
(C++11)(C++11)(C++11)
Typentransformationen
(C++11)(veraltet in C++23)
(C++11)(veraltet in C++23)
(C++11)
(C++11)(bis C++20*)(C++17)

(C++11)
(C++11)
(C++17)
Rationale Arithmetik zur Compilezeit
Ganzzahlsequenzen zur Compilezeit
 
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 Bi in B1, ..., BN ist, für den bool(Bi::value) == true gilt, oder BN, 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) [bearbeiten]
variadische logische AND-Metafunktion
(Klassenvorlage) [bearbeiten]