The deduction guide for std::array
requires all types be the same:
std::array arr = { 1, 2, 3.4 }; // error
What is the rationale behind such a requirement? Would there be any significant drawback if different types were allowed instead? For example:
namespace std {
template <typename... T>
array(T...) -> array<std::common_type_t<T...>, sizeof...(T)>;
}
std::array arr = { 1, 2, 3.4 }; // decltype(arr)::value_type deduced as double
There are substantial design issues with using common_type
. For example, std::common_type_t<A, B, C>
, std::common_type_t<C, A, B>
and std::common_type_t<C, B, A>
need not all exist - and if they do, need not be the same type:
struct A;
struct B;
struct C;
struct A { operator B(); };
struct B { operator C(); };
struct C { operator A(); };
static_assert(std::is_same_v<std::common_type_t<A, B, C>, C>);
static_assert(std::is_same_v<std::common_type_t<C, A, B>, B>);
static_assert(std::is_same_v<std::common_type_t<C, B, A>, A>);
That makes for an "interesting" user experience when reordering the elements of the initializer causes a different type to be deduced (or an error to be emitted).
It matches how function template arguments are deduced.
If they yield more than one possible deduced
A
, the type deduction fails.
[temp.deduct.call]/5
e.g.
template<typename T>
void foo(T, T){}
template<typename T>
struct bar{ bar(T, T) {} };
int main()
{
foo(1, 1.5); // error, note: deduced conflicting types for parameter 'T' ('int' and 'double')
bar(1, 1.5); // error, note: deduced conflicting types for parameter 'T' ('int' and 'double')
}
But you can provide a deduction guide for common types.
template<typename T>
struct baz{ baz(T, T) {} };
template<typename T, typename U>
baz(T, U) -> baz<std::common_type_t<T, U>>
or overloads that forward to common types
template<typename T>
void quux(T, T){}
template<typename T, typename U>
std::enable_if_t<!std::is_same<std::decay_t<T>, std::decay_t<U>>> quux(T t, U u)
{
using C = std::common_type_t<T, U>;
quux<C>(std::forward<C>(t), std::forward<C>(u)); // I think this is right
}
int main()
{
baz(1, 1.5);
quux(1, 1.5);
}
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