#ifndef RFL_MOVE_FROM_TUPLE_HPP_ #define RFL_MOVE_FROM_TUPLE_HPP_ #include #include #include "Array.hpp" #include "is_flatten_field.hpp" #include "is_named_tuple.hpp" #include "ptr_tuple_t.hpp" #include "tup_to_ptr_tuple.hpp" #include "tuple_t.hpp" namespace rfl { namespace internal { template constexpr int calc_flattened_size() { if constexpr (_i == std::tuple_size_v) { return 0; } else { using T = std::remove_pointer_t>; if constexpr (is_flatten_field_v) { return calc_flattened_size>() + calc_flattened_size(); } else { return 1 + calc_flattened_size(); } } } template auto unflatten_ptr_tuple(PtrTupleType& _t, 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 T = std::remove_cvref_t>>; if constexpr (is_flatten_field_v) { using SubTargetTupleType = ptr_tuple_t>; constexpr int flattened_size = calc_flattened_size(); return unflatten_ptr_tuple( _t, _args..., unflatten_ptr_tuple(_t) ); } else { return unflatten_ptr_tuple( _t, _args..., std::get<_j>(_t) ); } } } template auto move_from_pointers(Pointers& _ptrs, Args&&... _args) { constexpr auto i = sizeof...(Args); if constexpr (i == std::tuple_size_v>) { return std::remove_cvref_t { std::move(_args)... }; } else { using FieldType = std::tuple_element_t>; if constexpr (std::is_pointer_v) { return move_from_pointers(_ptrs, std::move(_args)..., std::move(*std::get(_ptrs))); } else { using PtrTupleType = ptr_tuple_t>; using U = std::remove_cvref_t< typename std::remove_pointer_t>::Type>; return move_from_pointers( _ptrs, std::move(_args)..., move_from_pointers(std::get(_ptrs)) ); } } } template auto flatten_array(T* _v) { return std::make_tuple(_v); } template auto flatten_array(std::array* _arr) { const auto fct = [](auto&... _v) { return std::tuple_cat(flatten_array(&_v)...); }; return std::apply(fct, *_arr); } template auto make_tuple_from_element(T _v) { return std::make_tuple(_v); } template auto make_tuple_from_element(Array* _arr) { return flatten_array(&(_arr->arr_)); } auto flatten_c_arrays(const auto& _tup) { const auto fct = [](auto... _v) { return std::tuple_cat(make_tuple_from_element(_v)...); }; return std::apply(fct, _tup); } /// Creates a struct of type T from a tuple by moving the underlying /// fields. template auto move_from_tuple(TupleType&& _t) { auto ptr_tuple = tup_to_ptr_tuple(_t); using TargetTupleType = tuple_t>; auto pointers = flatten_c_arrays(unflatten_ptr_tuple(ptr_tuple)); return move_from_pointers(pointers); } } // namespace internal } // namespace rfl #endif