std:: disjunction
|
Défini dans l'en-tête
<type_traits>
|
||
|
template
<
class
...
B
>
struct disjunction ; |
(depuis C++17) | |
Forme la disjonction logique des traits de type B... , effectuant efficacement un OU logique sur la séquence de traits.
La spécialisation std :: disjunction < B1, ..., BN > possède une base publique et non ambiguë qui est
- si sizeof... ( B ) == 0 , std:: false_type ; sinon
-
le premier type
BidansB1, ..., BNpour lequel bool ( Bi :: value ) == true , ouBNs'il n'existe pas un tel type.
Les noms des membres de la classe de base, à l'exception de
disjunction
et
operator=
, ne sont pas masqués et sont disponibles sans ambiguïté dans
disjunction
.
La disjonction est à court-circuit : s'il existe un argument de type template
Bi
avec
bool
(
Bi
::
value
)
!
=
false
, alors l'instanciation de
disjunction
<
B1, ..., BN
>
::
value
ne nécessite pas l'instanciation de
Bj
::
value
pour
j > i
.
Si le programme ajoute des spécialisations pour
std::disjunction
ou
std::disjunction_v
, le comportement est indéfini.
Table des matières |
Paramètres du modèle
| B... | - |
chaque argument de template
Bi
pour lequel
Bi
::
value
est instancié doit être utilisable comme classe de base et définir le membre
value
qui est convertible en
bool
|
Modèle de variable d'assistance
|
template
<
class
...
B
>
constexpr bool disjunction_v = disjunction < B... > :: value ; |
(depuis C++17) | |
Implémentation possible
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...>> {}; |
Notes
Une spécialisation de
disjunction
n'hérite pas nécessairement de
std::
true_type
ou de
std::
false_type
: elle hérite simplement du premier
B
dont la valeur
::value
, convertie explicitement en
bool
, est
true
, ou du tout dernier
B
lorsque tous se convertissent en
false
. Par exemple,
std
::
disjunction
<
std::
integral_constant
<
int
,
2
>
,
std::
integral_constant
<
int
,
4
>>
::
value
vaut
2
.
L'instanciation en court-circuit différencie
disjunction
des
expressions de repli
: une expression de repli comme
(
...
||
Bs
::
value
)
instancie chaque
B
dans
Bs
, tandis que
std
::
disjunction_v
<
Bs...
>
arrête l'instanciation dès que la valeur peut être déterminée. Ceci est particulièrement utile si le type suivant est coûteux à instancier ou peut provoquer une erreur grave lorsqu'il est instancié avec le mauvais type.
| Macro de test de fonctionnalité | Valeur | Norme | Fonctionnalité |
|---|---|---|---|
__cpp_lib_logical_traits
|
201510L
|
(C++17) | Traits de type d'opérateurs logiques |
Exemple
#include <cstdint> #include <string> #include <type_traits> // values_equal<a, b, T>::value est vrai si et seulement si 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 est toujours vrai template<typename T> struct default_type : std::true_type { using type = T; }; // Maintenant nous pouvons utiliser la disjonction comme une instruction switch : 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> // doit être le dernier ! >::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>); // vérifier si Foo est constructible à partir de double provoquera une erreur fatale 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 à retourner si rien n'est trouvé }; template<class... Args> using with = typename std::disjunction<is_constructible_x<Ts, Args...>..., fallback>::type; }; // OK, is_constructible<Foo, double> non instancié static_assert(std::is_same_v<first_constructible<std::string, int, Foo>::avec<double>, int>); static_assert(std::is_same_v<first_constructible<std::string, int>::avec<>, std::string>); static_assert(std::is_same_v<first_constructible<std::string, int>::avec<const char*>, std::string>); static_assert(std::is_same_v<first_constructible<std::string, int>::avec<void*>, void>); int main() {}
Voir aussi
|
(C++17)
|
métafonction logique NON
(modèle de classe) |
|
(C++17)
|
métafonction logique ET variadique
(modèle de classe) |