draconisplusplus/include/rfl/internal/wrap_in_fields.hpp

49 lines
1.7 KiB
C++
Raw Normal View History

2024-05-31 22:59:00 -04:00
#ifndef RFL_INTERNAL_WRAP_IN_FIELDS_HPP_
#define RFL_INTERNAL_WRAP_IN_FIELDS_HPP_
#include <tuple>
#include <type_traits>
#include "flattened_ptr_tuple_t.hpp"
#include "is_flatten_field.hpp"
#include "lit_name.hpp"
namespace rfl {
2024-06-08 14:10:59 -04:00
namespace internal {
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
template <class FieldNames, int j = 0, class... Fields>
auto wrap_in_fields(auto&& _tuple, Fields&&... _fields) {
constexpr auto size =
std::tuple_size_v<std::remove_cvref_t<decltype(_tuple)>>;
constexpr auto i = sizeof...(_fields);
if constexpr (i == size) {
return std::make_tuple(std::move(_fields)...);
} else {
auto value = std::move(std::get<i>(_tuple));
using Type =
std::remove_cvref_t<std::remove_pointer_t<decltype(value)>>;
if constexpr (is_flatten_field_v<Type>) {
// The problem here is that the FieldNames are already flattened, but
// this is not, so we need to determine how many field names to skip.
constexpr auto n_skip = std::tuple_size_v<
std::remove_cvref_t<flattened_ptr_tuple_t<typename Type::Type>>>;
return wrap_in_fields<FieldNames, j + n_skip>(
2024-06-08 15:53:06 -04:00
std::move(_tuple), std::move(_fields)..., std::move(value)
);
2024-06-08 14:10:59 -04:00
} else {
const auto name_literal = FieldNames::template name_of<j>();
2024-06-08 15:53:06 -04:00
auto new_field = rfl::make_field<
2024-06-08 14:10:59 -04:00
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
2024-06-08 15:53:06 -04:00
std::move(value)
);
2024-06-08 14:10:59 -04:00
return wrap_in_fields<FieldNames, j + 1>(
2024-06-08 15:53:06 -04:00
std::move(_tuple), std::move(_fields)..., std::move(new_field)
);
2024-06-08 14:10:59 -04:00
}
}
2024-05-31 22:59:00 -04:00
}
2024-06-08 14:10:59 -04:00
} // namespace internal
} // namespace rfl
2024-05-31 22:59:00 -04:00
#endif