[ACCEPTED]-What is the purpose of std::common_type?-c++11
std::common_type
was introduced for use with std::duration
--- if you 19 add a std::duration<int>
and a std::duration<short>
then the result should be 18 std::duration<int>
. Rather than specifying an endless stream 17 of allowed pairings, the decision was made 16 to delegate to a separate template which 15 found the result using the core language 14 rules applicable to the ?:
arithmetic-if operator.
People 13 then saw that this template might be generally 12 useful, and it was added as std::common_type
, and extended 11 to handle an arbitrary number of types. In 10 the C++0x library it is only used for pairs 9 of types though.
You should be able to use 8 the new SFINAE rules to detect whether or 7 not some instantiation of std::common_type
is valid. I haven't 6 tried though. In most cases if there isn't 5 a "common type" then there isn't anything 4 meaningful you can do anyway, so a compile 3 error is reasonable.
std::common_type
is not magic --- it 2 follows the rules of ?:
. If true?a:b
will compile, std::common_type<decltype(a),decltype(b)>::type
will 1 give you the type of the result.
Here are a few use cases of std::common_type
:
1. sum of variadic pack
Here is a version for variadic sum that 10 needs common_type
:
template<typename... T>
constexpr auto sum(T&&... values) {
std::common_type_t<T...> sum {}; // <= here we need std::common_type
// see code in the link above for the machinery of the below code
static_for<sizeof...(T)>([&](auto index) {
sum += get<index>(values...);
});
return sum;
}
Above example is using machinery 9 from this and this SO posts.
A note: you can achieve the 8 same with the following code without the need for common_type
:
template<typename T>
auto sum(T&& t) {
return t;
}
template<typename T, typename... Ts>
auto sum(T&& t, Ts&&... ts) {
return t + sum(std::forward<Ts>(ts)...);
}
2. requiring variadic pack to have a common type
Code below is based 7 on this SO post.
template <typename AlwaysVoid, typename... Ts>
struct has_common_type_impl : std::false_type {};
template <typename... Ts>
struct has_common_type_impl<std::void_t<std::common_type_t<Ts...>>, Ts...>
: std::true_type {};
template <typename... Ts>
concept has_common_type =
sizeof...(Ts) < 2 ||
has_common_type_impl<void, Ts...>::value;
template<typename... Ts> requires has_common_type<Ts...>
void foo(Ts&&... ts) {}
3. make_array from variadic pack
There was a pending proposal for the function make_array. For a discussion if there 6 still a need for make_array see this SO post.
A simple implementation 5 of make_array
would look like this:
template<typename... T>
constexpr auto make_array(T&&... values) requires has_common_type<T...> {
using TYPE = std::common_type_t<std::decay_t<T>...>;
return std::array<TYPE, sizeof...(T)>{static_cast<TYPE>(values)...};
}
with the following usage 4 examples:
constexpr auto arr1 = make_array(1, 2, 3);
constexpr auto arr2 = make_array(1, 2.5, 3);
using namespace std::string_literals;
auto arr3 = make_array("hello"s, "world");
Note that the proposal for make_array
had 3 an option to provide the actual requested 2 type, but in case it is not provided then 1 the common_type
is to be used.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.