Namespaces
Variants

std:: common_type

From cppreference.net
Metaprogramming library
Type traits
Type categories
(C++11)
(C++11) ( DR* )
Type properties
(C++11)
(C++11)
(C++14)
(C++11) (deprecated in C++26)
(C++11) ( until C++20* )
(C++11) (deprecated in C++20)
(C++11)
Type trait constants
Metafunctions
(C++17)
Supported operations
Relationships and property queries
Type modifications
Type transformations
(C++11) (deprecated in C++23)
(C++11) (deprecated in C++23)
(C++11)
(C++11) ( until C++20* ) (C++17)

common_type
(C++11)
(C++11)
(C++17)
Compile-time rational arithmetic
Compile-time integer sequences
定义于头文件 <type_traits>
template < class ... T >
struct common_type ;
(C++11 起)

确定所有类型 T... 中的公共类型,即所有 T... 均可显式转换到的类型。若存在此类类型(根据下述规则判定),则成员 type 将命名该类型。否则不存在成员 type

  • 如果 sizeof... ( T ) 为零,则不存在成员 type
  • 如果 sizeof... ( T ) 为一(即 T... 仅包含一个类型 T0 ),则成员 type std :: common_type < T0, T0 > :: type 类型相同(若该类型存在);否则不存在成员 type
  • 如果 sizeof... ( T ) 为二(即 T... 恰好包含两个类型 T1 T2 ),
  • 若对 T1 T2 中至少一个类型应用 std::decay 会产生不同类型,则成员 type 表示与 std :: common_type < std:: decay < T1 > :: type , std:: decay < T2 > :: type > :: type 相同的类型(若该类型存在);否则不存在成员 type
  • 否则,若存在针对 std :: common_type < T1, T2 > 的用户特化,则使用该特化;
  • 否则,若 std:: decay < decltype ( false ? std:: declval < T1 > ( ) : std:: declval < T2 > ( ) ) > :: type 是有效类型,则成员 type 表示该类型,参见 条件运算符
(C++20 起)
  • 否则,不存在成员 type
  • 如果 sizeof... ( T ) 大于二(即 T... 包含类型 T1, T2, R... ),那么当 std :: common_type < T1, T2 > :: type 存在时,成员 type 表示 std :: common_type < typename std :: common_type < T1, T2 > :: type , R... > :: type (如果该类型存在)。在所有其他情况下,不存在成员 type

如果参数包 T 中的任何类型不是完整类型、(可能带有 cv 限定符的) void 或未知边界的数组,则行为未定义。

如果上述模板的实例化直接或间接依赖于不完整类型,且该实例化在该类型被假设完成时可能产生不同结果,则行为未定义。

目录

嵌套类型

名称 定义
type 所有 T 的通用类型

辅助类型

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

特化

用户可以为类型 T1 T2 特化 common_type ,如果

  • 至少有一个 T1 T2 依赖于用户定义类型,且
  • 对于 T1 T2 两者, std::decay 都是恒等变换。

若该特化具有名为 type 的成员,则其必须是公开且无歧义的成员,且命名一个 cv 未限定的非引用类型, T1 T2 均可显式转换至该类型。此外, std :: common_type < T1, T2 > :: type std :: common_type < T2, T1 > :: type 必须表示同一类型。

违反这些规则添加 common_type 特化的程序具有未定义行为。

注意:程序若向 <type_traits> 头文件中除 std::basic_common_reference 外的任何其他模板 (C++20 起) 添加特化的行为是未定义的。

标准库已提供以下特化版本:

特化 std::common_type 特征
(类模板特化)
特化 std::common_type 特征
(类模板特化)
确定两个 pair 的公共类型
(类模板特化)
确定 tuple tuple-like 类型的公共类型
(类模板特化)
确定迭代器与适配的 basic_const_iterator 类型的公共类型
(类模板特化)

可能的实现

// 主模板(用于零个类型)
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 {};
// 3个及以上类型
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 << "  is  Number<int>{" << x.n << "}\n";
}
void describe(const char* 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);
}

输出:

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}

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 应用于 发布时的行为 正确行为
LWG 2141 C++11 条件运算符的结果类型未进行类型衰减 对结果类型进行衰减处理
LWG 2408 C++11 common_type 不支持SFINAE机制 使其支持SFINAE机制
LWG 2460 C++11 common_type 的特化几乎无法实现 减少了所需的
特化数量

参见

指定两种类型共享一个公共类型
(概念)