You can basically copy the implementation from cppreference's Possible implementation, chuck in a make_unique
and it just works:
#include <string>
#include <memory>
namespace detail {
template<class T, class Tuple, std::size_t... I>
constexpr std::unique_ptr<T> make_new_from_tuple_impl(Tuple&& t, std::index_sequence<I...>)
{
static_assert(std::is_constructible_v<T,
decltype(std::get<I>(std::declval<Tuple>()))...>);
#if __cpp_lib_reference_from_temporary >= 202202L
if constexpr (std::tuple_size_v<std::remove_reference_t<Tuple>> == 1) {
using tuple_first_t = decltype(std::get<0>(std::declval<Tuple>()));
static_assert(!std::reference_constructs_from_temporary_v<T, tuple_first_t>);
}
#endif
return std::make_unique<T>(std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
template<class T, class Tuple>
constexpr std::unique_ptr<T> make_new_from_tuple(Tuple&& t)
{
return detail::make_new_from_tuple_impl<T>(std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}
struct A
{
int i_; double d_; std::string s_;
A( int i, double d, const std::string& s ) : i_(i), d_(d), s_(s) {}
};
int main()
{
auto aTuple = std::make_tuple( 1, 1.5, std::string("Hello") );
auto a = make_new_from_tuple<A>(std::move(aTuple));
}
Or with raw pointers:
#include <string>
#include <memory>
namespace detail {
template<class T, class Tuple, std::size_t... I>
constexpr T* make_new_from_tuple_impl(Tuple&& t, std::index_sequence<I...>)
{
static_assert(std::is_constructible_v<T,
decltype(std::get<I>(std::declval<Tuple>()))...>);
#if __cpp_lib_reference_from_temporary >= 202202L
if constexpr (std::tuple_size_v<std::remove_reference_t<Tuple>> == 1) {
using tuple_first_t = decltype(std::get<0>(std::declval<Tuple>()));
static_assert(!std::reference_constructs_from_temporary_v<T, tuple_first_t>);
}
#endif
return new T(std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
template<class T, class Tuple>
constexpr T* make_new_from_tuple(Tuple&& t)
{
return detail::make_new_from_tuple_impl<T>(std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}
struct A
{
int i_; double d_; std::string s_;
A( int i, double d, const std::string& s ) : i_(i), d_(d), s_(s) {}
};
int main()
{
auto aTuple = std::make_tuple( 1, 1.5, std::string("Hello") );
auto a = make_new_from_tuple<A>(std::move(aTuple));
}