Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/reflection-cpp/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,7 @@ constexpr void EnumerateMembers(Callable&& callable)
}

template <typename Object, typename Callable>
requires std::same_as<void, std::invoke_result_t<Callable, std::string, MemberTypeOf<1, Object>>>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question here as I asked below (sorry) :-)

void CallOnMembers(Object& object, Callable&& callable)
{
EnumerateMembers<Object>(object,
Expand Down Expand Up @@ -751,6 +752,7 @@ constexpr ResultType FoldMembers(ResultType initialValue, Callable const& callab
///
/// @return The result of the fold
template <typename Object, typename Callable, typename ResultType>
requires std::same_as<ResultType, std::invoke_result_t<Callable, std::string, MemberTypeOf<1, Object>, ResultType>>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why std::string as first parameter? Shouldn't that be ResultType?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

callable is called in the following way:

result = callable(MemberNameOf<I, Object>, value, result);

so it must take MemberNameOf<I, Object> (std::string) as first argument and return result type which is ResultType
In the requires statement we first check that we can invoke callable with the required arguments
std::invoke_result_t<Callable, std::string, MemberTypeOf<1, Object>, ResultType>
and then check that returned type is ResultType in std::same_as<ResultType, std::invoke_result_t<>>

constexpr ResultType FoldMembers(Object& object, ResultType initialValue, Callable const& callable)
{
// clang-format off
Expand Down
50 changes: 50 additions & 0 deletions test-reflection-cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,56 @@ TEST_CASE("nested", "[reflection]")
CHECK(result == R"(a=1 b=2 c=3 d="hello" e={name="John Doe" email="[email protected]" age=42})");
}

TEST_CASE("EnumerateMembers.index_and_value", "[reflection]")
{
auto ps = Person { "John Doe", "[email protected]", 42 };
Reflection::EnumerateMembers(ps, []<size_t I>(auto&& value) {
if constexpr (I == 0)
{
CHECK(value == "John Doe");
}
else if constexpr (I == 1)
{
CHECK(value == "[email protected]");
}
else if constexpr (I == 2)
{
CHECK(value == 42);
}
});
}

TEST_CASE("EnumerateMembers.index_and_type", "[reflection]")
{
Reflection::EnumerateMembers<Person>([]<auto I, typename T>() {
if constexpr (I == 0)
{
static_assert(std::same_as<T,std::string_view>);
}
if constexpr (I == 1)
{
static_assert(std::same_as<T,std::string>);
}
if constexpr (I == 2)
{
static_assert(std::same_as<T,int>);
}
});
}

TEST_CASE("CallOnMembers", "[reflection]")
{
auto ps = Person { "John Doe", "[email protected]", 42 };
std::string result;
Reflection::CallOnMembers(ps, [&result](auto&& name, auto&& value) {
result += name;
result += "=";
result += std::format("{}", value);
result += " ";
});
CHECK(result == R"(name=John Doe [email protected] age=42 )");
}

TEST_CASE("FoldMembers.type", "[reflection]")
{
// clang-format off
Expand Down
Loading