Вы можете использовать std::apply
для создания пакета параметров и использовать его в инициализаторе:
auto someStruct = std::apply([](auto&&... args){return SomeStruct{decltype(args)(args)...};}, arr);
Вы можете поместить это в функцию для удобного использования:
template<typename T, typename A>
constexpr T make_from_tuple_list_init(A&& a) {
return std::apply([](auto&&... args){return T{decltype(args)(args)...};}, std::forward<A>(a));
}
Затем используйте его как
auto someStruct = make_from_tuple_list_init<SomeStruct>(arr);
Это требует C ++ 17 и #include<tuple>
, но может быть реализовано и в более ранних версиях C ++ (с некоторыми дополнительными усилиями). Также в C ++ 17 это гарантированно использует elision copy, поэтому будет создан только один SomeStruct
. До C ++ 17 могли быть задействованы некоторые конструкции перемещения (хотя компиляторы уже разрешили и реализовали оптимизацию возвращаемого значения с тем же эффектом).
std::apply
также имеет то преимущество, что работает с каждым типом, который реализует std::get
и std::tuple_size
, что означает, что он будет работать, например, с std::array
, std::tuple
, std::pair
и другими пользовательскими типами с этим интерфейсом.
Можно сделать два версии этой функции, одна из которых использует T{...}
, как указано выше, а другая - T(...)
, так что вы можете выбирать между инициализацией списка и прямой инициализацией.
Однако версия T(...)
был реализован в стандартной библиотеке с C ++ 17 как std::make_from_tuple
. В C ++ 20 агрегатная инициализация также будет работать с круглыми скобками, поэтому std::make_from_tuple
будет работать для вашего случая, тогда напрямую.
Для реализации C ++ 14, возьмите этот пример из Страница cppreference на std::make_from_tuple
:
namespace detail {
template <class T, class Tuple, std::size_t... I>
constexpr T make_from_tuple_impl( Tuple&& t, std::index_sequence<I...> )
{
return T(std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
template <class T, class Tuple>
constexpr T make_from_tuple( Tuple&& t )
{
return detail::make_from_tuple_impl<T>(std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}
и замените std::tuple_size_v<...>
на std::tuple_size<...>::value
.
Это для T(...)
версии. Вам нужно заменить T(...)
на T{...}
, чтобы получить версию T{...}
, которую я реализовал выше.