Skip to content

Commit 583f734

Browse files
Add Inspect() to public API
Signed-off-by: Christian Parpart <christian@parpart.family>
1 parent a62e214 commit 583f734

File tree

2 files changed

+30
-18
lines changed

2 files changed

+30
-18
lines changed

include/reflection-cpp/Reflection.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include <algorithm>
55
#include <array>
6+
#include <format>
7+
#include <string>
68
#include <string_view>
79
#include <tuple>
810
#include <type_traits>
@@ -389,4 +391,30 @@ consteval auto GetName()
389391
#endif
390392
}
391393

394+
template <typename Object>
395+
std::string Inspect(Object const& object)
396+
{
397+
return [&]<size_t... I>(std::index_sequence<I...>) {
398+
std::string str;
399+
auto onMember = [&str](auto&& name, auto&& value) {
400+
auto onValue = [&str]<typename T>(T&& arg) {
401+
// clang-format off
402+
if constexpr (std::is_convertible_v<T, std::string>
403+
|| std::is_convertible_v<T, std::string_view>
404+
|| std::is_convertible_v<T, char const*>) // clang-format on
405+
str += std::format("\"{}\"", arg);
406+
else
407+
str += std::format("{}", arg);
408+
};
409+
if (!str.empty())
410+
str += ' ';
411+
str += name;
412+
str += '=';
413+
onValue(value);
414+
};
415+
(onMember(MemberNameOf<I, Object>, std::get<I>(Reflection::ToTuple(object))), ...);
416+
return str;
417+
}(std::make_index_sequence<Reflection::CountMembers<Object>> {});
418+
}
419+
392420
} // namespace Reflection

test-reflection-cpp.cpp

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <catch2/catch_test_macros.hpp>
55

66
#include <iostream>
7-
#include <sstream>
87
#include <string>
98
#include <string_view>
109

@@ -15,19 +14,6 @@ struct Person
1514
int age;
1615
};
1716

18-
// TODO: This could be a public API function that prints all object members to a string (in a single-line)
19-
template <typename Object>
20-
std::string inspect(Object const& object)
21-
{
22-
auto const& tuple = Reflection::ToTuple(object);
23-
return [&]<size_t... I>(std::index_sequence<I...>) {
24-
std::stringstream str;
25-
((str << "Member " << I << " (" << Reflection::MemberNameOf<I, Object> << "): " << std::get<I>(tuple) << '\n'),
26-
...);
27-
return str.str();
28-
}(std::make_index_sequence<Reflection::CountMembers<Object>> {});
29-
}
30-
3117
enum Color
3218
{
3319
Red,
@@ -51,8 +37,6 @@ TEST_CASE("GetName", "[reflection]")
5137
TEST_CASE("core", "[reflection]")
5238
{
5339
auto p = Person { "John Doe", "john@doe.com", 42 };
54-
std::cout << "Elements: " << Reflection::CountMembers<Person> << '\n';
55-
std::cout << inspect(p);
56-
57-
// TODO: make this a real test
40+
auto const result = Reflection::Inspect(p);
41+
CHECK(result == R"(name="John Doe" email="john@doe.com" age=42)");
5842
}

0 commit comments

Comments
 (0)