std::common_type

From cppreference.com
< cpp‎ | types
 
 
Utilities library
Type support (basic types, RTTI, type traits)
Dynamic memory management
Error handling
Program utilities
Variadic functions
Date and time
Function objects
(C++11)
Relational operators
Optional and any
(C++17)
(C++17)
Pairs and tuples
(C++11)
(C++17)
Swap, forward and move
(C++14)
(C++11)
(C++11)
Type operations
(C++11)
(C++17)
 
Type support
Basic types
Fundamental types
Fixed width integer types (C++11)
Numeric limits
C numeric limits interface
Runtime type information
Type traits
Type categories
(C++11)
(C++14)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Type properties
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++14)
(C++11)
Type trait constants
Metafunctions
(C++17)
(C++17)
(C++17)
Supported operations
Relationships and property queries
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Type modifications
(C++11)(C++11)(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
Type transformations
(C++11)
(C++11)
(C++11)
(C++11)
(C++17)
(C++11)
common_type
(C++11)
(C++11)
(C++11)
 
Defined in header <type_traits>
template< class... T >
struct common_type;
(since C++11)

Determines the common type among all types T..., that is the type all T... can be implicitly converted to.

For non-specialized std::common_type, the rules for determining the common type between every pair T1, T2 are exactly the rules for determining the return type of the ternary conditional operator in unevaluated context, with arbitrary first argument of type bool and with xvalues of type T1 and T2 (since C++17)std::declval<T1>() and std::declval<T2>() (until C++17) as the second and the third operands. The common type is the result of std::decay applied to the type of the ternary conditional (since C++14).

If sizeof...(T) is zero or if there is no common type, the member type is not defined (std::common_type is SFINAE-friendly)

(since C++17)

Contents

[edit] Member types

Name Definition
type the common type for all T...

[edit] Helper types

template< class... T >
using common_type_t = typename common_type<T...>::type;
(since C++14)

[edit] Specializations

Custom specializations of the type trait std::common_type are allowed, as long as at least one parameter is a user-defined type (note that the behavior of a program that adds a specialization to any other class from <type_traits> is undefined).

The following specializations are already provided by the standard library:

specializes the std::common_type trait
(class template specialization)
specializes the std::common_type trait
(class template specialization)

[edit] Possible implementation

template <class ...T> struct common_type;
 
template <class T>
struct common_type<T> {
    typedef decay_t<T> type;
};
 
template <class T, class U>
struct common_type<T, U> {
    typedef decay_t<decltype(true ? std::declval<T>() : std::declval<U>())> type;
};
 
template <class T, class U, class... V>
struct common_type<T, U, V...> {
    typedef common_type_t<common_type_t<T, U>, V...> type;
};

[edit] Notes

For arithmetic types, the common type may be viewed as the type of the (possibly mixed-mode) arithmetic expression such as T0() + T1() + ... + Tn().

[edit] Examples

Demonstrates mixed-mode arithmetic on a user-defined class

#include <iostream>
#include <type_traits>
 
template <class T>
struct Number { T n; };
 
template <class T, class U>
Number<typename std::common_type<T, U>::type> operator+(const Number<T>& lhs,
                                                        const Number<U>& rhs) 
{
    return {lhs.n + rhs.n};
}
 
int main()
{
    Number<int> i1 = {1}, i2 = {2};
    Number<double> d1 = {2.3}, d2 = {3.5};
    std::cout << "i1i2: " << (i1 + i2).n << "\ni1d2: " << (i1 + d2).n << '\n'
              << "d1i2: " << (d1 + i2).n << "\nd1d2: " << (d1 + d2).n << '\n';
}

Output:

i1i2: 3
i1d2: 4.5
d1i2: 4.3
d1d2: 5.8