From a37668034078628f4b4155cc23ec1dd2ed06813a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 10 Dec 2024 15:26:36 -0800 Subject: [PATCH] [reflection] Add customization for_each_field() directly --- include/fixed_containers/reflection.hpp | 21 +++++++++++---- test/reflection_test.cpp | 35 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/include/fixed_containers/reflection.hpp b/include/fixed_containers/reflection.hpp index c4cc030e..e6c3e2d2 100644 --- a/include/fixed_containers/reflection.hpp +++ b/include/fixed_containers/reflection.hpp @@ -219,6 +219,20 @@ template inline constexpr auto FIELD_NAMES = fixed_containers::reflection_detail::field_names_of_impl< fixed_containers::reflection_detail::field_count_of_impl(std::decay_t{})>(std::decay_t{}); +template +struct ReflectionHelper +{ + template + static constexpr void for_each_field(T2&& instance, Func&& func) + { + auto tuple_view = tuples::as_tuple_view>.size()>(instance); + tuples::for_each_entry( + tuple_view, + [&func](std::size_t index, Field&& field) + { func(FIELD_NAMES>.at(index), std::forward(field)); }); + } +}; + } // namespace fixed_containers::reflection::customize namespace fixed_containers::reflection @@ -244,11 +258,8 @@ template requires(Reflectable>) constexpr void for_each_field(T&& instance, Func&& func) { - constexpr const auto& FIELD_NAMES = field_names_of(); - auto tuple_view = tuples::as_tuple_view(instance); - tuples::for_each_entry(tuple_view, - [&func](std::size_t index, Field&& field) - { func(FIELD_NAMES.at(index), std::forward(field)); }); + fixed_containers::reflection::customize::ReflectionHelper>::for_each_field( + std::forward(instance), std::forward(func)); } } // namespace fixed_containers::reflection diff --git a/test/reflection_test.cpp b/test/reflection_test.cpp index f6e449bc..2d141f47 100644 --- a/test/reflection_test.cpp +++ b/test/reflection_test.cpp @@ -628,6 +628,41 @@ inline constexpr auto fixed_containers::reflection::customize::FIELD_NAMES +struct fixed_containers::reflection::customize::ReflectionHelper +{ + template + requires std::same_as, MyCustomStruct> + static constexpr void for_each_field(T2&& instance, Func&& func) + { + // Apply it twice for unit testing purposes + func(FIELD_NAMES.at(0), instance.a); + func(FIELD_NAMES.at(1), instance.b); + func(FIELD_NAMES.at(2), instance.c); + + func(FIELD_NAMES.at(0), instance.a); + func(FIELD_NAMES.at(1), instance.b); + func(FIELD_NAMES.at(2), instance.c); + } +}; + static_assert(fixed_containers::reflection::field_names_of().size() == 3); +namespace fixed_containers +{ + +TEST(Reflection, Customization) +{ + constexpr auto RESULT = []() + { + MyCustomStruct instance{}; + std::size_t counter = 0; + reflection::for_each_field( + instance, [&](const std::string_view& /*name*/, const T&) { counter++; }); + return counter; + }(); + + static_assert(6 == RESULT); +} +} // namespace fixed_containers #endif