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