Skip to content

Commit 081ab6b

Browse files
committed
Implement CollectDifferences
1 parent 788bb64 commit 081ab6b

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

include/reflection-cpp/reflection.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,25 @@ std::string Inspect(std::vector<Object> const& objects)
811811
}
812812
return str;
813813
}
814+
815+
template <typename Object, typename Callback>
816+
void CollectDifferences(const Object& lhs, const Object& rhs, Callback&& callback)
817+
{
818+
template_for<0, CountMembers<Object>>([&]<auto I>() {
819+
if constexpr (std::equality_comparable<MemberTypeOf<I, Object>>)
820+
{
821+
if (GetMemberAt<I>(lhs) != GetMemberAt<I>(rhs))
822+
{
823+
callback(MemberNameOf<I, Object>, GetMemberAt<I>(lhs), GetMemberAt<I>(rhs));
824+
}
825+
}
826+
else
827+
{
828+
CollectDifferences(GetMemberAt<I>(lhs), GetMemberAt<I>(rhs), callback);
829+
}
830+
});
831+
}
832+
814833
} // namespace Reflection
815834

816835
template <std::size_t N>

test-reflection-cpp.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,53 @@ TEST_CASE("MemberTypeOf", "[reflection]")
102102
static_assert(std::same_as<Reflection::MemberTypeOf<3, TestStruct>, std::string>);
103103
static_assert(std::same_as<Reflection::MemberTypeOf<4, TestStruct>, Person>);
104104
}
105+
106+
struct Record
107+
{
108+
int id;
109+
std::string name;
110+
int age;
111+
};
112+
113+
TEST_CASE("Compare.simple", "[reflection]")
114+
{
115+
auto const r1 = Record { .id = 1, .name = "John Doe", .age = 42 };
116+
auto const r2 = Record { .id = 1, .name = "John Doe", .age = 42 };
117+
auto const r3 = Record { .id = 2, .name = "Jane Doe", .age = 43 };
118+
119+
std::string diff;
120+
auto differenceCallback = [&](std::string_view name, auto const& lhs, auto const& rhs) {
121+
diff += std::format("{}: {} != {}\n", name, lhs, rhs);
122+
};
123+
124+
Reflection::CollectDifferences(r1, r2, differenceCallback);
125+
CHECK(diff.empty());
126+
Reflection::CollectDifferences(r1, r3, differenceCallback);
127+
CHECK(diff == "id: 1 != 2\nname: John Doe != Jane Doe\nage: 42 != 43\n");
128+
}
129+
130+
struct Table
131+
{
132+
Record first;
133+
Record second;
134+
};
135+
136+
TEST_CASE("Compare.nested", "[reflection]")
137+
{
138+
auto const t1 = Table { .first = { .id = 1, .name = "John Doe", .age = 42 },
139+
.second = { .id = 2, .name = "Jane Doe", .age = 43 } };
140+
auto const t2 = Table { .first = { .id = 1, .name = "John Doe", .age = 42 },
141+
.second = { .id = 2, .name = "Jane Doe", .age = 43 } };
142+
auto const t3 = Table { .first = { .id = 1, .name = "John Doe", .age = 42 },
143+
.second = { .id = 3, .name = "Jane Doe", .age = 43 } };
144+
145+
std::string diff;
146+
auto differenceCallback = [&](std::string_view name, auto const& lhs, auto const& rhs) {
147+
diff += std::format("{}: {} != {}\n", name, lhs, rhs);
148+
};
149+
150+
Reflection::CollectDifferences(t1, t2, differenceCallback);
151+
CHECK(diff.empty());
152+
Reflection::CollectDifferences(t1, t3, differenceCallback);
153+
CHECK(diff == "id: 2 != 3\n");
154+
}

0 commit comments

Comments
 (0)