NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
reflect/any.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_REFLECT_ANY_HPP__
2#define NEFORCE_CORE_REFLECT_ANY_HPP__
3
11
14NEFORCE_BEGIN_NAMESPACE__
15NEFORCE_BEGIN_REFLECT__
16
22
23using type_id = size_t;
24
25
33template <typename T>
34struct type_name {
35 static constexpr string_view value = "unknown";
36};
37
41template <typename T>
42NEFORCE_INLINE17 constexpr string_view type_name_v = type_name<T>::value;
43
45#define __NEFORCE_SPECIALIZE_TYPE_NAME(T) \
46 template <> \
47 struct type_name<T> { \
48 static constexpr string_view value = #T; \
49 };
50
51NEFORCE_MACRO_RANGE_ARITHMETIC(__NEFORCE_SPECIALIZE_TYPE_NAME)
52#undef __NEFORCE_SPECIALIZE_TYPE_NAME
54
55
59template <typename T>
60NEFORCE_NODISCARD constexpr type_id type_id_for() noexcept {
61 if (type_name_v<T>.to_hash() != string_view("unknown").to_hash()) {
62 return type_name_v<T>.to_hash();
63 } else {
64#ifdef NEFORCE_COMPILER_MSVC
65 return FNV_hash_string(__FUNCSIG__, sizeof(__FUNCSIG__) - 1);
66#else
67 return FNV_hash_string(__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1);
68#endif
69 }
70}
71
72
79class meta_any {
80public:
81 static constexpr size_t SBO_SIZE = sizeof(void*) * 2;
82
83private:
90 union storage_internal {
91 storage_internal() noexcept = default;
92 storage_internal(const storage_internal&) = delete;
93 storage_internal& operator=(const storage_internal&) = delete;
94
95 void* ptr_ = nullptr;
96 aligned_storage_t<SBO_SIZE, alignof(_NEFORCE max_align_t)> buffer_;
97 };
98
103 enum class operation : uint8_t {
104 ACCESS,
105 GET_TYPE_ID,
106 COPY,
107 DESTROY,
108 MOVE,
109 };
110
115 union arg_t {
116 void* obj_ptr_{};
117 meta_any* any_ptr_;
118 reflect::type_id type_id_val_;
119 };
120
121 using manage_func = void (*)(operation, const meta_any*, arg_t*);
122
128 template <typename T>
129 struct internal_manage {
130 NEFORCE_NODISCARD static reflect::type_id type_id_val() noexcept { return type_id_for<T>(); }
131
132 template <typename... Args>
133 static void create(storage_internal& storage, Args&&... args) {
134 void* addr = const_cast<void*>(static_cast<const void*>(&storage.buffer_));
135 ::new (addr) T(_NEFORCE forward<Args>(args)...);
136 }
137
138 static T* access(const storage_internal& storage) noexcept {
139 const void* addr = &storage.buffer_;
140 return static_cast<T*>(const_cast<void*>(addr));
141 }
142
143 template <typename U = T, enable_if_t<is_copy_constructible_v<U>, int> = 0>
144 static void copy_op(const meta_any* self, arg_t* arg) {
145 auto* ptr = access(self->storage_);
146 create(arg->any_ptr_->storage_, *ptr);
147 arg->any_ptr_->manage_ = &manage;
148 arg->any_ptr_->type_id_ = type_id_val();
149 }
150
151 template <typename U = T, enable_if_t<!is_copy_constructible_v<U>, int> = 0>
152 static void copy_op(const meta_any* /*unused*/, arg_t* /*unused*/) {}
153
154 template <typename U = T, enable_if_t<is_move_constructible_v<U>, int> = 0>
155 static void move_op(const meta_any* self, arg_t* arg) {
156 auto* ptr = access(self->storage_);
157 create(arg->any_ptr_->storage_, _NEFORCE move(*ptr));
158 ptr->~T();
159 arg->any_ptr_->manage_ = &manage;
160 arg->any_ptr_->type_id_ = type_id_val();
161 }
162
163 template <typename U = T, enable_if_t<!is_move_constructible_v<U>, int> = 0>
164 static void move_op(const meta_any* /*unused*/, arg_t* /*unused*/) {}
165
166 static void manage(const operation op, const meta_any* self, arg_t* arg) {
167 auto* ptr = access(self->storage_);
168 switch (op) {
169 case operation::ACCESS: {
170 arg->obj_ptr_ = static_cast<void*>(ptr);
171 break;
172 }
173 case operation::GET_TYPE_ID: {
174 arg->type_id_val_ = type_id_val();
175 break;
176 }
177 case operation::COPY: {
178 copy_op(self, arg);
179 break;
180 }
181 case operation::DESTROY: {
182 ptr->~T();
183 break;
184 }
185 case operation::MOVE: {
186 move_op(self, arg);
187 break;
188 }
189 }
190 }
191 };
192
198 template <typename T>
199 struct external_manage {
200 NEFORCE_NODISCARD static reflect::type_id type_id_val() noexcept { return type_id_for<T>(); }
201
202 template <typename... Args>
203 static void create(storage_internal& storage, Args&&... args) {
204 storage.ptr_ = new T(_NEFORCE forward<Args>(args)...);
205 }
206
207 static T* access(const storage_internal& storage) noexcept { return static_cast<T*>(storage.ptr_); }
208
209 template <typename U = T, enable_if_t<is_copy_constructible_v<U>, int> = 0>
210 static void copy_op(const meta_any* self, arg_t* arg) {
211 auto* ptr = access(self->storage_);
212 create(arg->any_ptr_->storage_, *ptr);
213 arg->any_ptr_->manage_ = &manage;
214 arg->any_ptr_->type_id_ = type_id_val();
215 }
216
217 template <typename U = T, enable_if_t<!is_copy_constructible_v<U>, int> = 0>
218 static void copy_op(const meta_any* /*unused*/, arg_t* /*unused*/) {}
219
220 static void manage(const operation op, const meta_any* self, arg_t* arg) {
221 auto* ptr = access(self->storage_);
222 switch (op) {
223 case operation::ACCESS: {
224 arg->obj_ptr_ = static_cast<void*>(ptr);
225 break;
226 }
227 case operation::GET_TYPE_ID: {
228 arg->type_id_val_ = type_id_val();
229 break;
230 }
231 case operation::COPY: {
232 copy_op(self, arg);
233 break;
234 }
235 case operation::DESTROY: {
236 delete ptr;
237 break;
238 }
239 case operation::MOVE: {
240 arg->any_ptr_->storage_.ptr_ = self->storage_.ptr_;
241 arg->any_ptr_->manage_ = &manage;
242 arg->any_ptr_->type_id_ = type_id_val();
243 break;
244 }
245 }
246 }
247 };
248
252 template <typename T>
253 struct use_internal_storage : bool_constant<is_nothrow_move_constructible_v<T> && sizeof(T) <= SBO_SIZE &&
254 alignof(T) <= alignof(storage_internal)> {};
255
256 template <typename T>
257 using manage_t = conditional_t<use_internal_storage<T>::value, internal_manage<T>, external_manage<T>>;
258
259 manage_func manage_ = nullptr;
260 storage_internal storage_;
261 reflect::type_id type_id_ = 0;
262
263 void reset_internal() noexcept {
264 if (manage_ != nullptr) {
265 manage_(operation::DESTROY, this, nullptr);
266 manage_ = nullptr;
267 }
268 type_id_ = 0;
269 }
270
271 template <typename T, typename... Args, typename Manager = manage_t<decay_t<T>>>
272 void emplace_impl(Args&&... args) {
273 reset_internal();
274 Manager::create(storage_, _NEFORCE forward<Args>(args)...);
275 manage_ = &Manager::manage;
276 type_id_ = Manager::type_id_val();
277 }
278
279public:
283 meta_any() noexcept = default;
284
290 template <typename T, typename DecayT = decay_t<T>, typename = enable_if_t<!is_same_v<DecayT, meta_any>>,
291 typename = enable_if_t<is_copy_constructible_v<DecayT>>>
292 meta_any(T&& value) {
293 emplace_impl<T>(_NEFORCE forward<T>(value));
294 }
295
304 template <typename T, typename... Args>
305 void emplace(Args&&... args) {
306 emplace_impl<T>(_NEFORCE forward<Args>(args)...);
307 }
308
313 meta_any(const meta_any& other) {
314 if (other.manage_ != nullptr) {
315 arg_t arg;
316 arg.any_ptr_ = this;
317 other.manage_(operation::COPY, &other, &arg);
318 }
319 }
320
325 meta_any(meta_any&& other) noexcept {
326 if (other.manage_ != nullptr) {
327 arg_t arg;
328 arg.any_ptr_ = this;
329 other.manage_(operation::MOVE, &other, &arg);
330 other.manage_ = nullptr;
331 other.type_id_ = 0;
332 }
333 }
334
338 ~meta_any() { reset_internal(); }
339
345 meta_any& operator=(const meta_any& other) {
346 if (_NEFORCE addressof(other) == this) {
347 return *this;
348 }
349 reset_internal();
350 if (other.manage_ != nullptr) {
351 arg_t arg;
352 arg.any_ptr_ = this;
353 other.manage_(operation::COPY, &other, &arg);
354 }
355 return *this;
356 }
357
363 meta_any& operator=(meta_any&& other) noexcept {
364 if (_NEFORCE addressof(other) == this) {
365 return *this;
366 }
367 reset_internal();
368 if (other.manage_ != nullptr) {
369 arg_t arg;
370 arg.any_ptr_ = this;
371 other.manage_(operation::MOVE, &other, &arg);
372 other.manage_ = nullptr;
373 other.type_id_ = 0;
374 }
375 return *this;
376 }
377
382 NEFORCE_NODISCARD reflect::type_id type_id() const noexcept { return type_id_; }
383
388 NEFORCE_NODISCARD bool has_value() const noexcept { return manage_ != nullptr; }
389
394 explicit operator bool() const noexcept { return has_value(); }
395
401 template <typename T>
402 NEFORCE_NODISCARD T* cast() noexcept {
403 if (!manage_ || type_id_ != type_id_for<T>()) {
404 return nullptr;
405 }
406 arg_t arg;
407 manage_(operation::ACCESS, this, &arg);
408 return static_cast<T*>(arg.obj_ptr_);
409 }
410
416 template <typename T>
417 NEFORCE_NODISCARD const T* cast() const noexcept {
418 if (!manage_ || type_id_ != type_id_for<T>()) {
419 return nullptr;
420 }
421 arg_t arg;
422 manage_(operation::ACCESS, this, &arg);
423 return static_cast<const T*>(arg.obj_ptr_);
424 }
425
432 template <typename T>
433 NEFORCE_NODISCARD T& get() {
434 if (auto* ptr = cast<T>()) {
435 return *ptr;
436 }
437 NEFORCE_THROW_EXCEPTION(typecast_exception("Not a valid type"));
438 unreachable();
439 }
440
447 template <typename T>
448 NEFORCE_NODISCARD const T& get() const {
449 if (auto* ptr = cast<T>()) {
450 return *ptr;
451 }
452 NEFORCE_THROW_EXCEPTION(typecast_exception("Not a valid type"));
453 unreachable();
454 }
455
461 template <typename T>
462 NEFORCE_NODISCARD bool can_cast() const noexcept {
463 return cast<T>() != nullptr;
464 }
465
472 template <typename T>
473 NEFORCE_NODISCARD T convert() const {
474 if (auto* ptr = cast<T>()) {
475 return *ptr;
476 }
477 NEFORCE_THROW_EXCEPTION(typecast_exception("Not a valid type"));
478 unreachable();
479 }
480
485 NEFORCE_NODISCARD void* raw() noexcept {
486 if (manage_ == nullptr) {
487 return nullptr;
488 }
489 arg_t arg;
490 manage_(operation::ACCESS, this, &arg);
491 return arg.obj_ptr_;
492 }
493
497 NEFORCE_NODISCARD const void* raw() const noexcept {
498 if (manage_ == nullptr) {
499 return nullptr;
500 }
501 arg_t arg;
502 manage_(operation::ACCESS, this, &arg);
503 return arg.obj_ptr_;
504 }
505
509 void reset() noexcept { reset_internal(); }
510
515 void swap(meta_any& other) noexcept {
516 if (_NEFORCE addressof(other) == this) {
517 return;
518 }
519 meta_any tmp(_NEFORCE move(*this));
520 *this = _NEFORCE move(other);
521 other = _NEFORCE move(tmp);
522 }
523};
524
530inline void swap(meta_any& lhs, meta_any& rhs) noexcept { lhs.swap(rhs); }
531 // Reflection
533
534NEFORCE_END_REFLECT__
535NEFORCE_END_NAMESPACE__
536#endif // NEFORCE_CORE_REFLECT_ANY_HPP__
static constexpr size_t SBO_SIZE
SBO 缓冲区大小
异常处理框架
typename aligned_storage< Len, Align >::type aligned_storage_t
aligned_storage的便捷别名
double max_align_t
最大对齐类型
unsigned char uint8_t
8位无符号整数类型
constexpr size_t FNV_hash_string(const CharT *str, const size_t len) noexcept
字符串类型的FNV哈希
uint64_t size_t
无符号大小类型
size_t type_id
类型标识符
constexpr type_id type_id_for() noexcept
计算类型 T 的运行时期类型标识
constexpr string_view type_name_v
type_name 的便捷访问变量模板
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
basic_string_view< char > string_view
字符字符串视图
#define NEFORCE_MACRO_RANGE_ARITHMETIC(MAC)
所有算术类型列表宏
integral_constant< bool, Value > bool_constant
布尔常量包装器
字符串视图类型别名和实用函数