# [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.