std:: common_type
|
定义于头文件
<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
特征
(类模板特化) |
|
|
(C++23)
|
确定两个
pair
的公共类型
(类模板特化) |
|
(C++23)
|
确定
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
的特化几乎无法实现
|
减少了所需的
特化数量 |
参见
|
(C++20)
|
指定两种类型共享一个公共类型
(概念) |