sandbox
Loading...
Searching...
No Matches
description.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_REFLECTION_DESCROPTION_HPP_
3#define LIBSBX_REFLECTION_DESCROPTION_HPP_
4
5#include <concepts>
6#include <optional>
7#include <string_view>
8#include <tuple>
9
10#include <libsbx/reflection/member.hpp>
11#include <libsbx/reflection/enumerator.hpp>
12
13namespace sbx::reflection {
14
15template<typename Type>
17
18template<typename Type>
19concept reflectable_struct = std::is_class_v<Type> && requires() {
20 { description<Type>::name() } -> std::convertible_to<std::string_view>;
22}; // concept reflectable_struct
23
24template<typename Type>
25concept reflectable_enum = std::is_enum_v<Type> && requires() {
26 { description<Type>::name() } -> std::convertible_to<std::string_view>;
27 { description<Type>::enumerators() };
28}; // concept reflectable_struct
29
30template<typename Type>
31concept reflectable = reflectable_struct<Type> || reflectable_enum<Type>;
32
33template<reflectable_struct Type, typename Callback>
34auto for_each(Type& instance, Callback&& callback) -> void {
35 constexpr auto members = description<Type>::members();
36
37 std::apply([&](auto const&... field) {
38 (callback(field.name, instance.*(field.pointer)), ...);
39 }, members);
40}
41
42template<reflectable_struct Type, typename Callback>
43auto for_each(Type const& instance, Callback&& callback) -> void {
44 constexpr auto members = description<Type>::members();
45
46 std::apply([&](auto const&... field) {
47 (callback(field.name, instance.*(field.pointer)), ...);
48 }, members);
49}
50
51template<reflectable_struct Type, typename Callback>
52auto visit_member(Type& instance, std::string_view name, Callback&& callback) -> bool {
53 auto found = false;
54
55 for_each(instance, [&](auto member_name, auto& value) {
56 if (!found && member_name == name) {
57 callback(value);
58 found = true;
59 }
60 });
61
62 return found;
63}
64
65template<reflectable_enum Enum, typename Callback>
66auto for_each(Callback&& callback) -> void {
67 constexpr auto enumerators = description<Enum>::enumerators();
68
69 std::apply([&](auto const&... entry) {
70 (callback(entry.name, entry.value), ...);
71 }, enumerators);
72}
73
74template<reflectable_enum Enum>
75auto to_string(Enum value) -> std::string_view {
76 auto result = std::string_view{"<unknown>"};
77
78 for_each<Enum>([&](auto name, auto entry) {
79 if (entry == value) {
80 result = name;
81 }
82 });
83
84 return result;
85}
86
87template<reflectable_enum Enum>
88auto from_string(std::string_view name) -> std::optional<Enum> {
89 auto result = std::optional<Enum>{};
90
91 for_each<Enum>([&](auto entry_name, auto entry) {
92 if (entry_name == name) {
93 result = entry;
94 }
95 });
96
97 return result;
98}
99
100template<reflectable_enum Enum>
101auto from_string_or(std::string_view name, const Enum default_value) -> Enum {
102 auto result = from_string<Enum>(name);
103
104 return result ? *result : default_value;
105}
106
107} // namespace sbx::reflection
108
109#endif // LIBSBX_REFLECTION_DESCROPTION_HPP_
Definition: description.hpp:16