| Type traits | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time rational arithmetic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time integer sequences | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(C++14) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Defined in header <type_traits> | ||
template<class...T> struct common_type; | (since C++11) | |
Determines the common type among all typesT..., that is a type allT... can be explicitly converted to. If such a type exists (as determined according to the rules below), the membertype names that type. Otherwise, there is no membertype.
type.T... contains only one typeT0), the membertype names the same type asstd::common_type<T0, T0>::type if it exists; otherwise there is no membertype.T... contains exactly two typesT1 andT2),T1 andT2 produces a different type, the membertype names the same type asstd::common_type<std::decay<T1>::type,std::decay<T2>::type>::type, if it exists; if not, there is no membertype;type denotes that type, seethe conditional operator;
| (since C++20) |
type.T... consists of the typesT1, T2, R...), then ifstd::common_type<T1, T2>::type exists, the membertype denotesstd::common_type<typename std::common_type<T1, T2>::type, R...>::type if such a type exists. In all other cases, there is no membertype.If any type in the parameter packT is not a complete type, (possibly cv-qualified)void, or an array of unknown bound, the behavior is undefined.
If an instantiation of a template above depends, directly or indirectly, on an incomplete type, and that instantiation could yield a different result if that type were hypothetically completed, the behavior is undefined.
Contents |
| Name | Definition |
type | the common type for allT |
template<class...T> using common_type_t=typename common_type<T...>::type; | (since C++14) | |
Users may specializecommon_type for typesT1 andT2 if
T1 andT2 depends on a user-defined type, andT1 andT2.If such a specialization has a member namedtype, it must be a public and unambiguous member that names a cv-unqualified non-reference type to which bothT1 andT2 are explicitly convertible. Additionally,std::common_type<T1, T2>::type andstd::common_type<T2, T1>::type must denote the same type.
A program that addscommon_type specializations in violation of these rules has undefined behavior.
Note that the behavior of a program that adds a specialization to any other template(except forstd::basic_common_reference)(since C++20) from<type_traits> is undefined.
The following specializations are already provided by the standard library:
| specializes thestd::common_type trait (class template specialization)[edit] | |
| specializes thestd::common_type trait (class template specialization)[edit] | |
(C++23) | determines the common type of twopairs(class template specialization)[edit] |
(C++23) | determines the common type of atuple and atuple-like type(class template specialization)[edit] |
determines the common type of an iterator and an adaptedbasic_const_iterator type(class template specialization)[edit] |
// primary template (used for zero types)template<class...>struct common_type{}; // one typetemplate<class T>struct common_type<T>: common_type<T, T>{}; namespace detail{template<class...>using void_t=void; template<class T1,class T2>using conditional_result_t= decltype(false?std::declval<T1>():std::declval<T2>()); template<class,class,class=void>struct decay_conditional_result{};template<class T1,class T2>struct decay_conditional_result<T1, T2, void_t<conditional_result_t<T1, T2>>>:std::decay<conditional_result_t<T1, T2>>{}; template<class T1,class T2,class=void>struct common_type_2_impl: decay_conditional_result<const T1&,const T2&>{}; // C++11 implementation:// template<class, class, class = void>// struct common_type_2_impl {}; template<class T1,class T2>struct common_type_2_impl<T1, T2, void_t<conditional_result_t<T1, T2>>>: decay_conditional_result<T1, T2>{};} // two typestemplate<class T1,class T2>struct common_type<T1, T2>:std::conditional<std::is_same<T1,typenamestd::decay<T1>::type>::value&&std::is_same<T2,typenamestd::decay<T2>::type>::value, detail::common_type_2_impl<T1, T2>, common_type<typenamestd::decay<T1>::type,typenamestd::decay<T2>::type>>::type{}; // 3+ typesnamespace detail{template<class AlwaysVoid,class T1,class T2,class...R>struct common_type_multi_impl{};template<class T1,class T2,class...R>struct common_type_multi_impl<void_t<typename common_type<T1, T2>::type>, T1, T2, R...>: common_type<typename common_type<T1, T2>::type, R...>{};} template<class T1,class T2,class...R>struct common_type<T1, T2, R...>: detail::common_type_multi_impl<void, T1, T2, R...>{}; |
For arithmetic types not subject to promotion, the common type may be viewed as the type of the (possibly mixed-mode) arithmetic expression such asT0()+ T1()+ ...+ Tn().
Demonstrates mixed-mode arithmetic on a program-defined class:
#include <iostream>#include <type_traits> template<class T>struct Number{ T n;}; template<class T,class U>constexpr Number<std::common_type_t<T, U>> operator+(const Number<T>& lhs,const Number<U>& rhs){return{lhs.n+ rhs.n};} void describe(constchar* expr,const Number<int>& x){std::cout<< expr<<" is Number<int>{"<< x.n<<"}\n";} void describe(constchar* expr,const Number<double>& x){std::cout<< expr<<" is Number<double>{"<< x.n<<"}\n";} int main(){ Number<int> i1={1}, i2={2}; Number<double> d1={2.3}, d2={3.5}; describe("i1 + i2", i1+ i2); describe("i1 + d2", i1+ d2); describe("d1 + i2", d1+ i2); describe("d1 + d2", d1+ d2);}
Output:
i1 + i2 is Number<int>{3}i1 + d2 is Number<double>{4.5}d1 + i2 is Number<double>{4.3}d1 + d2 is Number<double>{5.8}The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 2141 | C++11 | the result type of the conditional operator was not decayed | decayed the result type |
| LWG 2408 | C++11 | common_type was not SFINAE-friendly | made SFINAE-friendly |
| LWG 2460 | C++11 | common_type specializations were nearly impossible to write | reduced the number of specializations needed |
(C++20) | specifies that two types share a common type (concept)[edit] |