C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
reflection.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include "char8_t_remediation.hpp"
26#include "meta/literal_string.hpp"
27#include "type_list.hpp"
28
29#include <cstddef>
30#include <span>
31#include <type_traits>
32#include <utility>
33
34namespace essence::meta::detail {
35 inline constexpr std::size_t max_fields = 256;
36
37 template <typename T>
38 consteval auto qualified_name_of_impl() noexcept {
39#ifdef _MSC_VER
40 // auto __cdecl essence::meta::detail::qualified_name_of_impl<T>(void) noexcept
41 constexpr std::size_t suffix_size{16};
42 constexpr std::string_view keyword{U8("essence::meta::detail::qualified_name_of_impl<")};
43 constexpr std::string_view signature{__FUNCSIG__};
44#elif defined(__GNUC__)
45 // consteval auto essence::name_of_impl() [with T = int]
46 constexpr std::size_t suffix_size{1};
47 constexpr std::string_view keyword{U8("[with T = ")};
48 constexpr std::string_view signature{__PRETTY_FUNCTION__};
49#elif defined(__clang__)
50 // auto essence::name_of_impl() [T = int]
51 constexpr std::size_t suffix_size{1};
52 constexpr std::string_view keyword{U8("[T = ")};
53 constexpr std::string_view signature{__PRETTY_FUNCTION__};
54#else
55#error "Unsupported compiler."
56#endif
57 constexpr auto prefix_size = signature.find(keyword) + keyword.size();
58 constexpr auto intermediate = signature.substr(prefix_size, signature.size() - prefix_size - suffix_size);
59
60 return meta::literal_string{
61 std::span<const char, intermediate.size()>{intermediate.data(), intermediate.size()}};
62 }
63} // namespace essence::meta::detail
64
65namespace essence::meta {
66 template <typename T>
67 concept reflectable =
68 std::same_as<T, typename T::es_meta_this_type> && type_list_like<typename T::es_meta_field_info_list_type>;
69
70 template <typename T, meta::literal_string Name, auto FieldPtr>
71 requires std::is_member_object_pointer_v<decltype(FieldPtr)>
72 struct field_info {
73 using type = T;
74
75 static constexpr auto&& name = Name;
76
77 template <typename U>
78 requires std::same_as<T, std::decay_t<U>>
79 static constexpr decltype(auto) value_ref(U&& obj) noexcept {
80 return (std::forward<U>(obj).*FieldPtr);
81 }
82 };
83
84 template <typename T>
86 static constexpr auto value = detail::qualified_name_of_impl<T>();
87 };
88
89 template <typename T>
90 inline constexpr auto&& qualified_name_of_v = qualified_name_of<T>::value;
91
92 template <typename T>
93 struct name_of {
94 static constexpr auto value = [] {
95 // struct a::b::c::class_name<nested1::nested2::nested3::nested_class_name<...>> ->
96 // class_name<...>
97 constexpr std::string_view qualified_name{qualified_name_of_v<T>};
98 constexpr auto template_argument_beginning_token_index = qualified_name.find_first_of(U8('<'));
99 constexpr auto scope_token_index = qualified_name.rfind(U8("::"), template_argument_beginning_token_index);
100 constexpr auto class_name_index = scope_token_index != std::string_view::npos ? scope_token_index + 2 : 0;
101 constexpr auto result = qualified_name.substr(class_name_index);
102
103 return meta::literal_string{std::span<const char, result.size()>{result.data(), result.size()}};
104 }();
105 };
106
107 template <typename T>
108 inline constexpr auto&& name_of_v = name_of<T>::value;
109
110 template <typename T>
112 struct get_fields {
113 using type = typename std::decay_t<T>::es_meta_field_info_list_type;
114 };
115
116 template <typename T>
117 using get_fields_t = typename get_fields<T>::type;
118
119 template <typename T, meta::literal_string Name>
122 using type = at_if_t<get_fields_t<T>, []<typename U>(std::type_identity<U>) { return U::name == Name; }>;
123 };
124
125 template <typename T, meta::literal_string Name>
126 using get_field_by_name_t = typename get_field_by_name<T, Name>::type;
127} // namespace essence::meta
128
129#define ES_MAKE_TERMINATOR_IMPL(suffix) using es_meta_terminator_##suffix = void
130#define ES_MAKE_TERMINATOR(suffix) ES_MAKE_TERMINATOR_IMPL(suffix)
131#define ES_META_MAKE_FIELD_INFO_NAME(name) es_meta_field_info_##name
132#define ES_META_GATHER_FIELDS decltype(es_meta_gather_fields(essence::rank<essence::meta::detail::max_fields>{}))
133
134#define ES_IDENTITY(...) decltype(static_cast<__VA_ARGS__ (*)()>(nullptr)())
135
136#define ES_BEGIN_FIELDS(type) \
137 using es_meta_this_type = type; \
138 static constexpr std::string_view es_meta_this_type_name{U8(#type)}; \
139 inline static essence::type_list<> es_meta_gather_fields(essence::rank<0>)
140
141#define ES_FIELD(type, name) \
142 type name{}; \
143 using ES_META_MAKE_FIELD_INFO_NAME(name) = \
144 essence::meta::field_info<es_meta_this_type, U8(#name), &es_meta_this_type::name>; \
145 inline static auto es_meta_gather_fields(essence::rank<ES_META_GATHER_FIELDS::size + 1>) \
146 -> essence::append_t<ES_META_GATHER_FIELDS, ES_META_MAKE_FIELD_INFO_NAME(name)>
147
148#define ES_END_FIELDS using es_meta_field_info_list_type = ES_META_GATHER_FIELDS
Definition reflection.hpp:67
Definition type_list.hpp:47
Definition reflection.hpp:72
Definition reflection.hpp:121
Definition reflection.hpp:112
A literal type of collection of chars.
Definition literal_string.hpp:41
Definition reflection.hpp:93
Definition reflection.hpp:85