I have a simple struct:
struct A
{
int a;
int b;
int c;
// A(int a, int b, int c) : a{a}, b{b}, c{c} { }
};
The constructor is commented for now. I am trying to create object of type A
in a such way:
auto t = std::make_tuple(1, 2, 3);
A a = std::make_from_tuple<A>(std::move(t));
but it doesn't compile. MSVC gives a message:
<function-style-cast>: cannot convert from initializer_list to _Ty
.
After I uncomment the constructor of struct A
, it starts working.
The question is: why std::make_from_tuple()
requires a user-defined constructor instead of default one?
CodePudding user response:
If you look closely at the implementation of make_from_tuple
in the standard:
namespace std {
template<class T, class Tuple, size_t... I>
requires is_constructible_v<T, decltype(get<I>(declval<Tuple>()))...>
constexpr T make-from-tuple-impl(Tuple&& t, index_sequence<I...>) {
return T(get<I>(std::forward<Tuple>(t))...);
}
}
It uses parentheses (()
) to initialize T
with direct initialization. Since A
is an aggregate, it cannot use parentheses for initialization in C 17, and can only use curly braces ({}
) for list initialization.
It is worth noting that P0960 makes it possible to use parentheses to initialize aggregates in C 20, so your code is well-formed in C 20.