#ifndef RFL_MOVE_FROM_NAMED_TUPLE_HPP_ #define RFL_MOVE_FROM_NAMED_TUPLE_HPP_ #include #include #include "is_field.hpp" #include "is_named_tuple.hpp" #include "nt_to_ptr_named_tuple.hpp" #include "ptr_field_tuple_t.hpp" #include "../named_tuple_t.hpp" namespace rfl { namespace internal { template auto make_ptr_fields(PtrNamedTupleType& _n, Args... _args) { constexpr auto i = sizeof...(Args); constexpr auto size = std::tuple_size_v>; if constexpr (i == size) { return std::make_tuple(_args...); } else { using Field = std::remove_cvref_t>; using T = std::remove_cvref_t>; if constexpr (is_named_tuple_v) { using SubPtrNamedTupleType = typename std::invoke_result), T>::type; return make_ptr_fields( _n, _args..., SubPtrNamedTupleType(_n).fields()); } else if constexpr (is_flatten_field::value) { using SubPtrFieldTupleType = std::remove_cvref_t>; return make_ptr_fields( _n, _args..., make_ptr_fields(_n)); } else { return make_ptr_fields( _n, _args..., _n.template get_field()); } } } template auto move_from_ptr_fields(Pointers& _ptrs, Args&&... _args) { constexpr auto i = sizeof...(Args); if constexpr (i == std::tuple_size_v>) { return T{std::move(_args)...}; } else { using FieldType = std::tuple_element_t>; if constexpr (is_field_v) { return move_from_ptr_fields( _ptrs, std::move(_args)..., rfl::make_field( std::move(*std::get(_ptrs).value()))); } else { using PtrFieldTupleType = std::remove_cvref_t>; using U = std::remove_cvref_t::Type>>; return move_from_ptr_fields( _ptrs, std::move(_args)..., move_from_ptr_fields(std::get(_ptrs))); } } } /// Creates a struct of type T from a named tuple by moving the underlying /// fields. template T move_from_named_tuple(NamedTupleType&& _n) { using RequiredType = std::remove_cvref_t>; if constexpr (is_named_tuple_v>) { return std::move(_n); } else if constexpr (std::is_same, RequiredType>()) { auto ptr_named_tuple = nt_to_ptr_named_tuple(_n); using PtrFieldTupleType = std::remove_cvref_t>; auto pointers = make_ptr_fields(ptr_named_tuple); return move_from_ptr_fields(pointers); } else { return move_from_named_tuple(RequiredType(std::move(_n))); } } } // namespace internal } // namespace rfl #endif