diff --git a/include/reflection-cpp/reflection.hpp b/include/reflection-cpp/reflection.hpp index ad3ca12..ae7a240 100644 --- a/include/reflection-cpp/reflection.hpp +++ b/include/reflection-cpp/reflection.hpp @@ -604,9 +604,11 @@ namespace detail template constexpr void enumerate_types(F&& f) { - [&f](std::index_sequence) { + [&f](std::index_sequence) + { (f.template operator()(), ...); - }(std::index_sequence_for {}); + } + (std::index_sequence_for {}); } template @@ -625,9 +627,22 @@ constexpr void template_for(F&& f) { using t = std::common_type_t; - [&f](std::integer_sequence) { + [&f](std::integer_sequence) + { detail::for_values<(B + Xs)...>(f); - }(std::make_integer_sequence {}); + } + (std::make_integer_sequence {}); +} + +template +constexpr void template_for(F&& f) +{ + using t = typename ElementMask::value_type; + [&f](std::integer_sequence) + { + Reflection::detail::for_values<(Xs)...>(f); + } + (ElementMask {}); } template @@ -674,6 +689,22 @@ consteval auto GetName() #endif } +/// Calls a callable on members of an object specified with ElementMask sequence with the index of the member as the +/// first argument. and the member's default-constructed value as the second argument. +template +constexpr void EnumerateMembers(Object& object, Callable&& callable) +{ + template_for([&]() { callable.template operator()(GetMemberAt(object)); }); +} + +/// Calls a callable on members of an object specified with ElementMask sequence with the index and member's type as +/// template arguments. +template +constexpr void EnumerateMembers(Callable&& callable) +{ + template_for([&]() { callable.template operator()>(); }); +} + /// Calls a callable on each member of an object with the index of the member as the first argument. /// and the member's default-constructed value as the second argument. template @@ -688,7 +719,7 @@ constexpr void EnumerateMembers(Callable&& callable) { // clang-format off template_for<0, CountMembers>( - [&]() { + [&]() { callable.template operator()>(); } ); @@ -699,7 +730,7 @@ template requires std::same_as>> void CallOnMembers(Object& object, Callable&& callable) { - EnumerateMembers(object, + EnumerateMembers(object, [&](T&& value) { callable(MemberNameOf, value); }); } @@ -738,7 +769,7 @@ constexpr ResultType FoldMembers(Object& object, ResultType initialValue, Callab { // clang-format off ResultType result = initialValue; - EnumerateMembers( + EnumerateMembers( object, [&](MemberType&& value) { result = callable(MemberNameOf, value, result); diff --git a/test-reflection-cpp.cpp b/test-reflection-cpp.cpp index 10d187b..11d35f4 100644 --- a/test-reflection-cpp.cpp +++ b/test-reflection-cpp.cpp @@ -5,6 +5,7 @@ #include #include +#include struct Person { @@ -136,6 +137,25 @@ TEST_CASE("EnumerateMembers.index_and_type", "[reflection]") }); } +TEST_CASE("EnumerateMembers.partial", "[reflection]") +{ + Reflection::EnumerateMembers, Person>([]() { + if constexpr (I == 0) + { + static_assert(std::same_as); + } + if constexpr (I == 1) + { + static_assert(false); + } + if constexpr (I == 2) + { + static_assert(std::same_as); + } + }); +} + + TEST_CASE("CallOnMembers", "[reflection]") { auto ps = Person { .name = "John Doe", .email = "john@doe.com", .age = 42 }; @@ -247,3 +267,10 @@ TEST_CASE("Compare.nested", "[reflection]") Reflection::CollectDifferences(t1, t3, differenceCallback); CHECK(diff == "id: 2 != 3\n"); } + +TEST_CASE("TemplateFor over sequence", "[refleciton]") +{ + std::string result {}; + Reflection::template_for>([&](){result += std::to_string(I);}); + CHECK(result == "321"); +}