◐ Shell
clean mode source ↗

std::common_type - cppreference.com

确定所有类型 T... 的公共类型,即所有 T... 都能显式转换到的类型。如果这种类型(根据以下规则确定)存在,那么成员 type 指名该类型。否则,没有成员 type

如果这种特化拥有名为 type 的成员,那么限定标识 std::common_type<T1, T2>::type 必须合法并指名一个 T1T2 都能显式转换到的,无 cv 限定且非引用的类型。而且,std::common_type<T1, T2>::typestd::common_type<T2, T1>::type 必须指代同一类型。

// 主模板(用于零个类型)
template<class...>
struct common_type {};

// 一个类型
template<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 实现:
    // 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> {};
}

// 两个类型
template<class T1, class T2>
struct common_type<T1, T2> 
    : std::conditional<std::is_same<T1, typename std::decay<T1>::type>::value &&
                       std::is_same<T2, typename std::decay<T2>::type>::value,
                       detail::common_type_2_impl<T1, T2>,
                       common_type<typename std::decay<T1>::type,
                                   typename std::decay<T2>::type>>::type {};

// 三个及以上类型
namespace 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...> {};

对于不提升的算术类型,共用类型可视为如 T0() + T1() + ... + Tn() 的(可以为混合模式的)算术表达式的类型。

演示由程序定义的类上的混合模式算术:

#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(const char* expr, const Number<int>& x)
{
    std::cout << expr << "  是  Number<int>{" << x.n << "}\n";
}

void describe(const char* expr, const Number<double>& x)
{
    std::cout << expr << "  是  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);
}

输出:

i1 + i2  是  Number<int>{3}
i1 + d2  是  Number<double>{4.5}
d1 + i2  是  Number<double>{4.3}
d1 + d2  是  Number<double>{5.8}