Skip to content

Commit 41f8f55

Browse files
Fixes problem of working on structs with only a single element
Signed-off-by: Christian Parpart <[email protected]>
1 parent c7226db commit 41f8f55

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

include/reflection-cpp/reflection.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ namespace detail
146146

147147
template <class T, class... Args>
148148
requires(std::is_aggregate_v<std::remove_cvref_t<T>>)
149-
inline constexpr auto CountMembers = [] {
149+
inline constexpr auto CountMembers = []() constexpr {
150150
using V = std::remove_cvref_t<T>;
151151
if constexpr (requires { V { Args {}..., detail::any_t {} }; })
152152
{
@@ -463,8 +463,20 @@ constexpr decltype(auto) GetMemberAt(T&& t)
463463
}
464464

465465
/// Represents the type of the member at index I of type Object
466+
// template <auto I, typename Object>
467+
// using MemberTypeOf = std::remove_cvref_t<decltype(std::get<I>(ToTuple(Object {})))>;
468+
466469
template <auto I, typename Object>
467-
using MemberTypeOf = std::remove_cvref_t<decltype(std::get<I>(ToTuple(Object {})))>;
470+
using MemberTypeOf = decltype([]() constexpr {
471+
if constexpr (CountMembers<Object> == 1)
472+
{
473+
// Work around the problem of trying to construct a get<0>(tuple) with only a single field member.
474+
auto const [p0] = Object {};
475+
return p0;
476+
}
477+
else
478+
return std::get<I>(ToTuple(Object {}));
479+
}());
468480

469481
template <class T>
470482
struct WrappedPointer final

test-reflection-cpp.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ enum Color
3030
Blue
3131
};
3232

33+
struct SingleValueRecord
34+
{
35+
int value;
36+
};
37+
3338
TEST_CASE("GetName", "[reflection]")
3439
{
3540
auto const enumValue = Reflection::GetName<Color::Red>();
@@ -38,13 +43,34 @@ TEST_CASE("GetName", "[reflection]")
3843
auto const enumValue2 = Reflection::GetName<Color::Green>();
3944
CHECK(enumValue2 == "Green");
4045

41-
auto const person = Person { "John Doe", "[email protected]", 42 };
4246
auto const memberName1 = Reflection::GetName<&Person::email>();
4347
CHECK(memberName1 == "email");
48+
49+
auto const singleValueField = Reflection::GetName<&SingleValueRecord::value>();
50+
CHECK(singleValueField == "value");
51+
}
52+
53+
TEST_CASE("single value record", "[reflection]")
54+
{
55+
static_assert(Reflection::CountMembers<SingleValueRecord> == 1);
56+
57+
auto const s = SingleValueRecord { 42 };
58+
auto const t = Reflection::ToTuple(s);
59+
60+
CHECK(std::get<0>(t) == 42);
61+
CHECK(Reflection::GetMemberAt<0>(s) == 42);
62+
63+
Reflection::CallOnMembers(s, [](auto&& name, auto&& value) {
64+
CHECK(name == "value");
65+
CHECK(value == 42);
66+
});
4467
}
4568

4669
TEST_CASE("core", "[reflection]")
4770
{
71+
auto s = SingleValueRecord { 42 };
72+
CHECK(Reflection::Inspect(s) == "value=42");
73+
4874
auto p = Person { "John Doe", "[email protected]", 42 };
4975
auto const result = Reflection::Inspect(p);
5076
CHECK(result == R"(name="John Doe" email="[email protected]" age=42)");

0 commit comments

Comments
 (0)