cpp-reflect
C++ Reflection and Annotations Library
Loading...
Searching...
No Matches
type_name.cppm
Go to the documentation of this file.
1// Copyright (c) 2024-2025, Víctor Castillo Agüero.
2// SPDX-License-Identifier: GPL-3.0-or-later
3
8
9module;
10#include <cstddef>
11
12#if defined(__clang__) || defined(__GNUC__)
13#define REFL_PRETTY_FUNCTION __PRETTY_FUNCTION__
14#elif defined(_MSC_VER)
15#define REFL_PRETTY_FUNCTION __FUNCSIG__
16#else
17#error "unsupported compiler (pretty function)"
18#endif
19
20export module reflect:type_name;
21
22import std;
23
24import :types;
25
26export namespace refl {
27 namespace detail { // Yoinked from JDH's implementation
28 // type_name adapted from:
29 // https://bitwizeshift.github.io/posts/2021/03/09/getting-an-unmangled-type-name-at-compile-time/
30 template <std::size_t... Is>
31 constexpr auto substring_as_array(std::string_view s, std::index_sequence<Is...>) {
32 return std::array{s[Is]..., '\0'};
33 }
34
35 template <typename T>
36 constexpr auto type_name_array() {
37#if defined(__clang__)
38 constexpr auto prefix = std::string_view{"[T = "};
39 constexpr auto suffix = std::string_view{"]"};
40#elif defined(__GNUC__)
41 constexpr auto prefix = std::string_view{"with T = "};
42 constexpr auto suffix = std::string_view{"]"};
43#elif defined(_MSC_VER)
44 constexpr auto prefix = std::string_view{"type_name_array<"};
45 constexpr auto suffix = std::string_view{">(void)"};
46#else
47#error "unsupported compiler (type_name_array)"
48#endif
49
50 constexpr auto function = std::string_view{REFL_PRETTY_FUNCTION};
51 constexpr auto start = function.find(prefix) + prefix.size();
52 constexpr auto end = function.rfind(suffix);
53
54 static_assert(start < end);
55
56 constexpr auto name = function.substr(start, (end - start));
57 constexpr auto size = name.size();
58 // As of right now, this next line shows an error in the IDE because it thinks
59 // that 'size' is maybe not known at compile time. Making this function a consteval
60 // didn't help. Don't know how to silence this. It compiles fine.
61 return substring_as_array(name, std::make_index_sequence<size>{});
62 }
63 template <template <typename...> typename Pack>
64 constexpr auto type_name_array_pack() {
65#if defined(__clang__)
66 constexpr auto prefix = std::string_view{"[Pack = "};
67 constexpr auto suffix = std::string_view{"]"};
68#elif defined(__GNUC__)
69 constexpr auto prefix = std::string_view{"with T = "};
70 constexpr auto suffix = std::string_view{"]"};
71#elif defined(_MSC_VER)
72 constexpr auto prefix = std::string_view{"type_name_array<"};
73 constexpr auto suffix = std::string_view{">(void)"};
74#else
75#error "unsupported compiler (type_name_array)"
76#endif
77
78 constexpr auto function = std::string_view{REFL_PRETTY_FUNCTION};
79 constexpr auto start = function.find(prefix) + prefix.size();
80 constexpr auto end = function.rfind(suffix);
81
82 static_assert(start < end);
83
84 constexpr auto name = function.substr(start, (end - start));
85 constexpr auto size = name.size();
86 // As of right now, this next line shows an error in the IDE because it thinks
87 // that 'size' is maybe not known at compile time. Making this function a consteval
88 // didn't help. Don't know how to silence this. It compiles fine.
89 return substring_as_array(name, std::make_index_sequence<size>{});
90 }
91 template <template <typename T, std::size_t I> typename Pack>
92 constexpr auto type_name_array_pack_1t1i() {
93#if defined(__clang__)
94 constexpr auto prefix = std::string_view{"[T = "};
95 constexpr auto suffix = std::string_view{"]"};
96#elif defined(__GNUC__)
97 constexpr auto prefix = std::string_view{"with T = "};
98 constexpr auto suffix = std::string_view{"]"};
99#elif defined(_MSC_VER)
100 constexpr auto prefix = std::string_view{"type_name_array<"};
101 constexpr auto suffix = std::string_view{">(void)"};
102#else
103#error "unsupported compiler (type_name_array)"
104#endif
105
106 constexpr auto function = std::string_view{REFL_PRETTY_FUNCTION};
107 constexpr auto start = function.find(prefix) + prefix.size();
108 constexpr auto end = function.rfind(suffix);
109
110 static_assert(start < end);
111
112 constexpr auto name = function.substr(start, (end - start));
113 constexpr auto size = name.size();
114 // As of right now, this next line shows an error in the IDE because it thinks
115 // that 'size' is maybe not known at compile time. Making this function a consteval
116 // didn't help. Don't know how to silence this. It compiles fine.
117 return substring_as_array(name, std::make_index_sequence<size>{});
118 }
119
120
121 template <typename T>
123 static inline constexpr auto value = type_name_array<T>();
124 };
125 template <template <typename...> typename Pack>
127 static inline constexpr auto value = type_name_array_pack<Pack>();
128 };
129 template <template <typename T, std::size_t I> typename Pack>
131 static inline constexpr auto value = type_name_array_pack_1t1i<Pack>();
132 };
133
134
135 template <typename T>
136 constexpr auto type_name_str() {
137 constexpr auto& val = type_name_holder<T>::value;
138 return std::string_view{val.data(), val.size() - 1};
139 }
140 template <template <typename...> typename Pack>
141 constexpr auto type_name_str_pack() {
142 constexpr auto& val = type_name_holder_pack<Pack>::value;
143 return std::string_view{val.data(), val.size() - 1};
144 }
145 template <template <typename T, std::size_t I> typename Pack>
146 constexpr auto type_name_str_pack_1t1i() {
147 constexpr auto& val = type_name_holder_pack_1t1i<Pack>::value;
148 return std::string_view{val.data(), val.size() - 1};
149 }
150
151
152 constexpr std::uint64_t fnv1a_partial(std::uint64_t partial, std::string_view s) {
153 if (s.length() == 0) {
154 return 0;
155 }
156
157 partial = (partial ^ s[0]) * 1099511628211u;
158 return s.length() == 1 ? partial : fnv1a_partial(partial, s.substr(1));
159 }
160
161 // constexpr FNV1a hash
162 constexpr std::uint64_t fnv1a_append(std::uint64_t partial, std::string_view s) {
163 if (s.length() >= 256) {
164 return fnv1a_append(fnv1a_partial(partial, s.substr(0, 256)), s.substr(256));
165 } else {
166 return fnv1a_partial(partial, s);
167 }
168 }
169
170 constexpr std::uint64_t fnv1a(std::string_view s) {
171 return fnv1a_append(14695981039346656037u, s);
172 }
173
174 } // namespace detail
175
176 template <typename T>
178
179 template <template <typename...> typename Pack>
181
182 template <template <typename T, std::size_t I> typename Pack>
184
185 template <typename T>
187
188 template <template <typename...> typename Pack>
190
191 template <template <typename T, std::size_t I> typename Pack>
193
194 namespace detail {
195 template <typename T>
197 static constexpr type_id_t value = type_id<T>;
198 };
199 template <template <typename...> typename Pack, typename... Ts>
200 struct pack_type_id<Pack<Ts...>> {
201 static constexpr type_id_t value = pack_id<Pack>;
202 };
203 template <template <typename, std::size_t> typename Pack, typename T, std::size_t I>
204 struct pack_type_id<Pack<T, I>> {
206 };
207 }
208
209 template <typename T>
211}
constexpr std::uint64_t fnv1a_append(std::uint64_t partial, std::string_view s)
constexpr auto type_name_array()
constexpr auto type_name_str()
constexpr auto type_name_array_pack_1t1i()
constexpr std::uint64_t fnv1a_partial(std::uint64_t partial, std::string_view s)
constexpr auto type_name_str_pack()
constexpr std::uint64_t fnv1a(std::string_view s)
constexpr auto substring_as_array(std::string_view s, std::index_sequence< Is... >)
constexpr auto type_name_str_pack_1t1i()
constexpr auto type_name_array_pack()
constexpr auto pack_1t1i_name
constexpr type_id_t pack_1t1i_id
std::size_t type_id_t
Definition _types.cppm:30
constexpr type_id_t type_id
constexpr auto pack_name
constexpr auto type_name
constexpr type_id_t pack_type_id
constexpr type_id_t pack_id
static constexpr type_id_t value
static constexpr auto value