| Type traits | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time rational arithmetic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time integer sequences | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(C++14) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Defined in header <type_traits> | ||
template<class...B> struct disjunction; | (since C++17) | |
Forms thelogical disjunction of the type traitsB..., effectively performing a logical OR on the sequence of traits.
The specializationstd::disjunction<B1, ..., BN> has a public and unambiguous base that is
Bi inB1, ..., BN for whichbool(Bi::value)==true, orBN if there is no such type.The member names of the base class, other thandisjunction andoperator=, are not hidden and are unambiguously available indisjunction.
Disjunction is short-circuiting: if there is a template type argumentBi withbool(Bi::value)!=false, then instantiatingdisjunction<B1, ..., BN>::value does not require the instantiation ofBj::value forj > i.
If the program adds specializations forstd::disjunction orstd::disjunction_v, the behavior is undefined.
Contents |
| B... | - | every template argumentBi for whichBi::value is instantiated must be usable as a base class and define membervalue that is convertible tobool |
template<class...B> constexprbool disjunction_v= disjunction<B...>::value; | (since 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...>>{}; |
A specialization ofdisjunction does not necessarily inherit from of eitherstd::true_type orstd::false_type: it simply inherits from the firstB whose::value, explicitly converted tobool, istrue, or from the very lastB when all of them convert tofalse. For example,std::disjunction<std::integral_constant<int,2>,std::integral_constant<int,4>>::value is2.
The short-circuit instantiation differentiatesdisjunction fromfold expressions: a fold expression like(...|| Bs::value) instantiates everyB inBs, whilestd::disjunction_v<Bs...> stops instantiation once the value can be determined. This is particularly useful if the later type is expensive to instantiate or can cause a hard error when instantiated with the wrong type.
| Feature-test macro | Value | Std | Feature |
|---|---|---|---|
__cpp_lib_logical_traits | 201510L | (C++17) | Logical operator type traits |
#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 truetemplate<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 errorstruct 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{staticconstexprbool 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 instantiatedstatic_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<constchar*>,std::string>);static_assert(std::is_same_v<first_constructible<std::string,int>::with<void*>,void>); int main(){}
(C++17) | logical NOT metafunction (class template)[edit] |
(C++17) | variadic logical AND metafunction (class template)[edit] |