Skip to content

Commit 4ded85e

Browse files
Merge pull request #10 from contour-terminal/improvement/Lightweight-related
Some additions and tweaks
2 parents c842e24 + 83f5e4c commit 4ded85e

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

include/reflection-cpp/reflection.hpp

+55-3
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ inline constexpr decltype(auto) ToTuple(T&& t) noexcept
202202
{
203203
if constexpr (N == 0)
204204
return std::tuple {};
205-
//clang-format off
205+
// clang-format off
206206
else if constexpr (N == 1)
207207
{
208208
auto& [p0] = t;
@@ -453,7 +453,7 @@ inline constexpr decltype(auto) ToTuple(T&& t) noexcept
453453
auto& [p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49] = t;
454454
return std::tie(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49);
455455
}
456-
//clang-format on
456+
// clang-format on
457457
}
458458

459459
template <class T>
@@ -683,12 +683,64 @@ consteval auto GetName()
683683
}
684684

685685
template <typename Object, typename Callable>
686-
decltype(auto) CallOnMembers(Object const& object, Callable&& callable)
686+
void CallOnMembers(Object const& object, Callable&& callable)
687687
{
688688
template_for<0, Reflection::CountMembers<Object>>(
689689
[&]<auto I>() { callable(Reflection::MemberNameOf<I, Object>, std::get<I>(Reflection::ToTuple(object))); });
690690
}
691691

692+
template <typename Object, typename Callable>
693+
void CallOnMembers(Object& object, Callable&& callable)
694+
{
695+
template_for<0, Reflection::CountMembers<Object>>(
696+
[&]<auto I>() { callable(Reflection::MemberNameOf<I, Object>, std::get<I>(Reflection::ToTuple(object))); });
697+
}
698+
699+
/// Folds over the members of a type without an object of it.
700+
///
701+
/// @param initialValue The initial value to fold with
702+
/// @param callable The callable to fold with. The parameters are the member name,
703+
/// the member's default value and the current result of the fold.
704+
///
705+
/// @return The result of the fold
706+
template <typename Object, typename Callable, typename ResultType>
707+
constexpr ResultType FoldMembers(ResultType initialValue, Callable const& callable)
708+
{
709+
// clang-format off
710+
ResultType result = initialValue;
711+
template_for<0, Reflection::CountMembers<Object>>(
712+
[&]<size_t I>() {
713+
result = callable(Reflection::MemberNameOf<I, Object>,
714+
std::get<I>(Reflection::ToTuple(Object {})),
715+
result);
716+
}
717+
);
718+
// clang-format on
719+
return result;
720+
}
721+
722+
/// Folds over the members of an object
723+
///
724+
/// @param object The object to fold over
725+
/// @param initialValue The initial value to fold with
726+
/// @param callable The callable to fold with. The parameters are the member name,
727+
/// the member value and the current result of the fold.
728+
///
729+
/// @return The result of the fold
730+
template <typename Object, typename Callable, typename ResultType>
731+
constexpr ResultType FoldMembers(Object const& object, ResultType initialValue, Callable const& callable)
732+
{
733+
// clang-format off
734+
ResultType result = initialValue;
735+
template_for<0, Reflection::CountMembers<Object>>([&]<size_t I>() {
736+
result = callable(Reflection::MemberNameOf<I, Object>,
737+
std::get<I>(Reflection::ToTuple(object)),
738+
result);
739+
});
740+
return result;
741+
// clang-format on
742+
}
743+
692744
template <typename Object>
693745
std::string Inspect(Object const& object)
694746
{

test-reflection-cpp.cpp

+26-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ TEST_CASE("vector", "[reflection]")
5959
CHECK(result == R"(name="John Doe" email="[email protected]" age=42
6060
name="John Doe" email="[email protected]" age=43
6161
)");
62-
//clang-format on
6362
}
6463

6564
TEST_CASE("nested", "[reflection]")
@@ -68,3 +67,29 @@ TEST_CASE("nested", "[reflection]")
6867
auto const result = Reflection::Inspect(ts);
6968
CHECK(result == R"(a=1 b=2 c=3 d="hello" e={name="John Doe" email="[email protected]" age=42})");
7069
}
70+
71+
TEST_CASE("FoldMembers.type", "[reflection]")
72+
{
73+
// clang-format off
74+
auto const result = Reflection::FoldMembers<TestStruct>(0, [](auto&& /*name*/, auto&& /*value*/, auto&& result) {
75+
return result + 1;
76+
});
77+
// clang-format on
78+
CHECK(result == 5);
79+
}
80+
81+
struct S
82+
{
83+
int a {};
84+
int b {};
85+
int c {};
86+
};
87+
88+
TEST_CASE("FoldMembers.value", "[reflection]")
89+
{
90+
auto const s = S { 1, 2, 3 };
91+
auto const result = Reflection::FoldMembers(
92+
s, 0, [](auto&& /*name*/, auto&& memberValue, auto&& accum) { return accum + memberValue; });
93+
94+
CHECK(result == 6);
95+
}

0 commit comments

Comments
 (0)