Since C++11 the type trait std::common_type
was introduced. std::common_type
determines the common type between all of its template arguments. In C++14 its helper type std::common_type_t
was also introduce in order to make code that uses std::common_type
type trait shorter.
std::common_type
is particular useful in overloaded arithmetic operators, e.g.,
template<typename T1, typename T2>
std::common_type_t<T1, T2> operator+(T1 const &t1, T2 const &t2) {
return t1 + t2;
}
It works fine if its templates arguments are built in types (e.g., int
, double
). However I doesn't seem to work if I provide as template arguments to it user defined types e.g.,
struct A {};
struct B {};
std::common_type_t<A, B> // doesn't work
Q: How I can make std::common_type
trait work with user defined types?
According to the draft standard N4582 §20.13.2 Header synopsis [meta.type.synop] (Emphasis Mine):
The behavior of a program that adds specializations for any of the templates defined in this subclause is undefined unless otherwise specified.
Consequently, adding specializations for type_traits
can cause undefined behaviour unless somewhere else in the standard there's a wording for a specific type trait that supersedes the wording displayed above. Fortunately, in Table 60 - Other transformations:
There's the wording:
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 ]
This means that specializations of std::common_type
type trait that have at least one user-defined type are perfectly allowed. In fact if you take a look at §20.15.4.3 Specializations of common_type [time.traits.specializations] you'll find out that STL already defines specializations of std::common_type
for user defined types std::chrono::duration
and std::chrono::time_point
.
Thus, the correct way to make common_type
"work" for user defined types is to provide a specialization of it for those specific types, e.g.,
struct A {};
struct B {};
namespace std {
template<>
struct common_type<A, B> {
using type = A;
};
}
In the code example above we specify that the common type between A
and B
is A
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With