25#include "../common_types.hpp"
26#include "../detail/data_member_binding.hpp"
27#include "../naming_convention.hpp"
28#include "../struct.hpp"
37namespace essence::meta::runtime {
43 requires std::is_class_v<T>
68 requires std::is_class_v<T>
69 std::span<const std::string> get_data_member_names() {
70 static const auto cache = [] {
71 std::vector<std::string> result;
73 for (
auto&& item : meta::probe_data_member_names<T>()) {
74 result.emplace_back(std::string{item});
89 template <naming_convention Convention,
typename T>
90 requires std::is_class_v<T>
91 std::span<const data_member_info<T>> get_data_member_info() {
92 static const auto cache = [] {
93 std::vector<data_member_info<T>> result;
95 for (
auto&& item : get_data_member_names<T>()) {
96 result.emplace_back(item, convert_naming_convention(item, Convention));
113 template <naming_convention Convention = naming_convention::none,
typename T,
typename Callable>
114 requires std::is_class_v<std::decay_t<T>>
115 void enumerate_data_members(T&& obj, Callable&& handler) {
116 using decayed_type = std::decay_t<T>;
118 static const auto cache = get_data_member_info<Convention, decayed_type>();
119 static constexpr auto make_ref_info = []<
typename U>(
const data_member_info<decayed_type>& item, U& reference) {
121 using enclosing_type = decayed_type;
123 const std::string& enclosing_type_name;
124 const std::string& raw_name;
125 const std::string& name;
130 .enclosing_type_name = item.enclosing_type_name,
131 .raw_name = item.raw_name,
133 .reference = reference,
137 auto pointers = detail::make_data_member_pointers(std::forward<T>(obj));
138 auto tuple = std::forward_as_tuple(std::forward<Callable>(handler));
140 [&]<std::size_t... Is>(std::index_sequence<Is...>) {
142 [&pointers]<
typename InnerCallable>(InnerCallable&& handler) {
143 std::forward<InnerCallable>(handler)(make_ref_info(cache[Is], *std::get<Is>(pointers))...);
146 }(std::make_index_sequence<std::tuple_size_v<
decltype(pointers)>>{});