std::common_type 用户定义类型的特征

std::common_type trait for user defined types

自 C++11 以来,引入了类型特征 std::common_typestd::common_type 确定其所有模板参数之间的公共类型。在 C++14 中,还引入了辅助类型 std::common_type_t 以缩短使用 std::common_type 类型特征的代码。

std::common_type 在重载算术运算符中特别有用,例如,

template<typename T1, typename T2>
std::common_type_t<T1, T2> operator+(T1 const &t1, T2 const &t2) {
  return t1 + t2;
}

如果它的模板参数是内置类型(例如,intdouble),它工作正常。但是,如果我将用户定义类型作为模板参数提供给它,我似乎无法工作,例如

struct A {};
struct B {};

std::common_type_t<A, B> // doesn't work

:如何使 std::common_type 特征与用户定义的类型一起工作?

根据标准草案N4582 §20.13.2 Header 概要[meta.type.synop](强调我的):

The behavior of a program that adds specializations for any of the templates defined in this subclause is undefined unless otherwise specified.

因此,为 type_traits 添加特化可能会导致未定义的行为,除非标准中的其他地方有特定类型特征的措辞取代上面显示的措辞。幸运的是,在 Table 60 - 其他转换:

有这样的措辞:

A program may specialize this trait if at least one template parameter in the specialization is a user-defined type. [ Note: Such specializations are needed when only explicit conversions are desired among the template arguments. — end note ]

这意味着 std::common_type 类型特征的特化具有至少一种 user-defined 类型是完全允许的。事实上,如果您查看 §20.15.4.3 common_type [time.traits.specializations] 的特化,您会发现 STL 已经定义了 [=12 的特化=] 对于用户定义的类型 std::chrono::durationstd::chrono::time_point.

因此,为用户定义的类型创建 common_type "work" 的正确方法是为这些特定类型提供特化,例如,

struct A {};
struct B {};

namespace std {
  template<>
  struct common_type<A, B> {
    using type = A;
  };
} 

在上面的代码示例中,我们指定AB之间的公共类型是A