CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
Box.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
10#include "Forward.hpp"
11
12#include "MetaError.hpp"
13#include "Type.hpp"
14#include "IReflectable.hpp"
15
17
21
22#include <cassert>
23
24namespace CeresEngine {
25
26 class TypeInfo;
27 class Type;
28
29 class MetaArgument;
30
31 namespace internal {
32 template<typename T>
33 using is_class_ptr = std::conditional_t<std::is_pointer_v<std::remove_reference_t<T>> && std::is_class_v<std::remove_pointer_t<std::remove_reference_t<T>>>,
34 std::true_type, std::false_type>;
35 template<typename T> using is_class_ptr_t = typename is_class_ptr<T>::type;
36 template<typename T> constexpr auto is_class_ptr_v = is_class_ptr_t<T>::value;
37 } // namespace internal
38
40 class Box {
41 private:
42 static constexpr const size_t kSmallSize = sizeof(void*) * 2;
43
45 union Storage {
47 void* ptr;
48
52
53 explicit Storage() : ptr(nullptr) {}
54 };
55
58
60 const TypeInfo* mTypeInfo = nullptr;
61
62 public: // Views
65 class Array;
66
70 class Map;
71
74 class Iterable;
75
79 class Iterator;
80
83 class Pointer;
84
87 class WeakPointer;
88
89 public:
92
94 Box(const Box& other);
95
97 Box& operator=(const Box& other);
98
100 Box(Box&& other) noexcept;
101
104
107 Box(T&& value);
108
111 Box& operator=(T&& value);
112
115
117
118 template<typename T, typename... Args> static Box create(Args&&... args) {
119 return Box(std::in_place_type_t<T>{}, std::forward<Args>(args)...);
120 }
121
122 explicit Box(const void* ptr, const TypeInfo* typeInfo);
123
126
127 private:
129
130 public:
133
136
139
141 [[nodiscard]] explicit operator bool() const noexcept { return !empty(); }
142
144 friend bool operator==(const Box& lhs, const Box& rhs);
145
147 friend bool operator!=(const Box& lhs, const Box& rhs) { return !operator==(lhs, rhs); }
148
149#if !CE_COMPILER_MSVC && 0
151 template<typename T> requires(!std::is_same_v<T, Box>)
152 [[nodiscard]] friend bool operator==(const Box& lhs, const T& rhs) {
153 return lhs == Box(std::cref(rhs));
154 }
155
157 template<typename T> requires(!std::is_same_v<T, Box>)
158 [[nodiscard]] friend bool operator!=(const Box* lhs, const T& rhs) {
159 return !(lhs == rhs);
160 }
161#endif
162
164 template<typename T> [[nodiscard]] bool eq(const T& value) const;
165
167 template<typename T> [[nodiscard]] bool neq(const T& value) const { return !eq(value); }
168
169 public: // Type information
172
175
178
181
183 template<typename T> [[nodiscard]] bool is() const {
184 return is(CeresEngine::getType<T>());
185 }
186
187 [[nodiscard]] bool is(const Type& type) const;
188
189 public:
192 [[nodiscard]] Box copy() const;
193
194 public:
198
202
206
209 [[nodiscard]] Box ref() && { return std::move(*this).rref(); }
210
213 template<typename T> [[nodiscard]] T& ref() const& {
214 using U = std::remove_reference_t<T>;
215
216 const TypeID fromID = getInternalTypeID(std::is_const_v<T> ? TypeAttribute::LREF_CONST : TypeAttribute::LREF);
218
219 U* const result = TypeCastOperation<U>::invoke(*this, fromID, toID);
220 return *result;
221 }
222
223 template<> [[nodiscard]] Box& ref<Box>() const& {
224 return const_cast<Box&>(*this);
225 }
226
229 template<typename T> [[nodiscard]] T&& ref() && { return std::move(*this).rref<T>(); }
230
231 template<> [[nodiscard]] Box&& ref<Box>() && {
232 return std::move(*this);
233 }
234
237 template<typename T> [[nodiscard]] const T& cref() const { return ref<std::add_const_t<std::remove_reference_t<T>>>(); }
238
239 template<> [[nodiscard]] const Box& cref<Box>() const {
240 return *this;
241 }
242
245 template<typename T> [[nodiscard]] T&& rref() && {
246 using U = std::remove_reference_t<T>;
247
250
251 auto* result = TypeCastOperation<U>::invoke(*this, fromID, toID);
252 return std::move(*result);
253 }
254
255 template<> [[nodiscard]] Box&& rref<Box>() && {
256 return std::move(*this);
257 }
258
260 [[nodiscard]] void* data() noexcept { return const_cast<void*>(std::as_const(*this).data()); }
261
263 [[nodiscard]] const void* data() const noexcept;
264
269 using U = std::remove_reference_t<T>;
270
271 const TypeID fromID = getInternalTypeID(std::is_const_v<T> ? TypeAttribute::LREF_CONST : TypeAttribute::LREF);
273 try {
274 return TypeCastOperation<U>::invoke(*this, fromID, toID);
275 } catch(...) {
276 return nullptr;
277 }
278 }
279
280 // /// Checks if the value held by the variant is convertible to `T`.
281 // /// \tparam T The check conversion.
282 // template<typename T> [[nodiscard]] bool canConvert() {
283 // static_assert(!std::is_reference_v<T>, "Type cannot be reference");
284 //
285 // if(is<T>()) {
286 // return true;
287 // }
288 //
289 // const TypeID fromID = getInternalTypeID(TypeAttribute::LREF);
290 // const TypeID toID = getTypeID<T>();
291 // if(Type::hasConverter(fromID, toID)) {
292 // return true;
293 // }
294 //
295 // return false;
296 // }
297
300 template<typename T> [[nodiscard]] bool canConvert() const {
301 static_assert(!std::is_reference_v<T>, "Type cannot be reference");
302
303 if(mTypeInfo == nullptr) {
304 return false;
305 }
306
307 if(is<T>()) {
308 return true;
309 }
310
312 return canConvert(toID);
313 }
314
316 [[nodiscard]] bool canConvert(const TypeID& target) const { return canConvert(Type(target)); }
317
319 [[nodiscard]] bool canConvert(const Type& target) const {
320 if(target.mTypeInfo == nullptr) {
321 return false;
322 }
323 return canConvert(*target.mTypeInfo);
324 }
325
327 [[nodiscard]] bool canConvert(const TypeInfo& target) const;
328
332 template<typename T> [[nodiscard]] T to() const& {
333 static_assert(!std::is_reference_v<T>, "Type cannot be reference");
334
335 std::aligned_storage_t<sizeof(T), alignof(T)> buffer;
336
338 TypeConversionOperation<T>::invoke(*this, typeID, &buffer);
339 CE_SCOPE_EXIT { reinterpret_cast<T*>(&buffer)->~T(); };
340 return std::move(*reinterpret_cast<T*>(&buffer));
341 }
342
343 template<> [[nodiscard]] Box to<Box>() const& {
344 return *this;
345 }
346
348 [[nodiscard]] Box to(const TypeID& target) const { return to(Type(target)); }
349
351 [[nodiscard]] Box to(const Type& target) const {
352 if(target.mTypeInfo == nullptr) {
353 return nullptr;
354 }
355 return to(*target.mTypeInfo);
356 }
357
359 [[nodiscard]] Box to(const TypeInfo& target) const;
360
364 template<typename T> void convert() { *this = to<T>(); }
365
371 template<typename T> [[nodiscard]] bool tryConvert() {
372 try {
373 *this = to<T>();
374 return true;
375 } catch(...) {
376 return false;
377 }
378 }
379
380 private:
381 void* cast();
382
383 public: // Views
387
391
395
399
403
404 private:
406 [[nodiscard]] void* storage() noexcept { return const_cast<void*>(std::as_const(*this).storage()); }
407
409 [[nodiscard]] const void* storage() const noexcept { return isSmall() ? mStorage.buffer : mStorage.ptr; }
410
411 friend struct std::hash<CeresEngine::Box>;
412 friend void swap(Box&, Box&) noexcept;
414
415 void* allocate(const TypeInfo* typeInfo);
417
420 void swap(Box& other) noexcept;
421
423 [[nodiscard]] TypeID getInternalTypeID(TypeAttribute attr = TypeAttribute::NONE) const noexcept;
424
427
430
433
436 };
437
438 inline void swap(Box& lhs, Box& rhs) noexcept { lhs.swap(rhs); }
439
440 // template<typename T> struct Box::TypeCheckOperation {
441 // public:
442 // /// Performs the variant type check operaton.
443 // /// \param self The variant to perform a type check against.
444 // /// \param typeID The type to check.
445 // static bool invoke(const Box& self, const TypeID typeID) {
446 // using Decay = full_decay<T>;
447 // using C = std::remove_pointer_t<Decay>;
448 //
449 // if(self.empty()) {
450 // return false;
451 // }
452 //
453 // const Type from = Type{typeID};
454 // const Type to = Type{CeresEngine::getTypeID<T>()};
455 //
456 // if(Type::compatible(from, to) && from.getDecayTypeID() == to.getDecayTypeID()) {
457 // return true;
458 // }
459 //
460 // if constexpr(std::is_class_v<Decay> || internal::is_class_ptr_v<Decay>) {
461 // const Class* const fromClass = self.getClassType().getClass();
462 // const Class* const toClass = Class::find(CeresEngine::getTypeID<C>());
463 // if(fromClass == nullptr || toClass == nullptr) {
464 // return false;
465 // }
466 //
467 // return fromClass->inheritedFrom(toClass);
468 // }
469 //
470 // return false;
471 // }
472 // };
473
474 namespace impl {
475 [[nodiscard]] const void* castInternal(const Box& self, const Type& type);
476 }
477
478 template<typename T> struct Box::TypeCastOperation {
479 private:
481 using C = std::remove_pointer_t<Decay>;
482 using tag_t = std::conditional_t<std::is_class_v<Decay>, std::integral_constant<int, 1>,
483 std::conditional_t<internal::is_class_ptr_v<Decay>, std::integral_constant<int, 2>, std::integral_constant<int, 0>>>;
484
485 public:
486 [[nodiscard]] static T* invoke(const Box& self, const TypeID fromID, const TypeID toID) {
487 using namespace std::literals;
488
489 if(self.empty()) {
490 throw BadMetaValueCast("Box is empty");
491 }
492
493 const Decay* result = nullptr;
494
495 const Type from = Type{fromID};
496 const Type to = Type{toID};
497 if(Type::compatible(from, to)) {
498 if(from.getDecayTypeID() == to.getDecayTypeID()) {
499 result = static_cast<const Decay*>(self.data());
500 } else if(const void* const ptr = cast(self, from, tag_t{})) {
501 result = static_cast<const Decay*>(ptr);
502 }
503 }
504
505 if(!result) {
506 result = static_cast<const Decay*>(self.data());
507 info("{0} -> {1}", from.getTypeName(), to.getTypeName());
508 throw BadMetaValueCast("Incompatible types: {} -> {}", from.getTypeName(), to.getTypeName());
509 }
510
511 if constexpr(std::is_array_v<T>) {
512 return reinterpret_cast<T*>(*result);
513 } else {
514 return const_cast<T*>(result);
515 }
516 }
517
518 private:
519 // nope
520 [[nodiscard]] static const void* cast(const Box&, Type, std::integral_constant<int, 0>) { return nullptr; }
521
522 // class
523 [[nodiscard]] static const void* cast(const Box& self, const Type from, std::integral_constant<int, 1>) {
524 return from.isClass() ? impl::castInternal(self, CeresEngine::getType<T>()) : nullptr;
525 }
526
527 // class ptr
528 [[nodiscard]] static const void* cast(const Box& self, const Type from, std::integral_constant<int, 2>) {
529 if(!from.isClassPtr()) {
530 return nullptr;
531 }
532
533 const void* const ptr = impl::castInternal(self, CeresEngine::getType<T>());
534 if(ptr == nullptr) {
535 return nullptr;
536 }
537
538 if(ptr != self.mStorage.ptr) {
539 throw BadMetaValueCast("Reference to sub-object pointers isn't supported");
540 }
541
542 return &self.mStorage.ptr;
543 }
544 };
545
546 template<typename T> struct Box::TypeConversionOperation {
547 static_assert(!std::is_array_v<T>, "Array types aren't supported");
548
549 static void invoke(const Box& self, const TypeID typeID, void* const buffer) {
550 CE_ASSERT(buffer != nullptr);
551 if(self.empty()) {
552 throw BadMetaValueConvert("Box is empty");
553 }
554
555 const Type from(typeID);
557 if(Type::compatible(from, to)) {
558 if(from.getDecayTypeID() == to.getDecayTypeID()) {
559 to.copyConstruct(self.data(), buffer);
560 return;
561 } else if(cast(self, from, to, buffer, tag_t{})) {
562 return;
563 }
564 }
565
566 if(Type::convert(self.data(), from, buffer, to)) {
567 return;
568 }
569
570 throw BadMetaValueConvert("Incompatible types: {0} -> {1}", from.getTypeName(), to.getTypeName());
571 }
572
573 private:
575 using C = std::remove_pointer_t<Decay>;
576 using tag_t = std::conditional_t<std::is_class_v<Decay>, std::integral_constant<int, 1>,
577 std::conditional_t<internal::is_class_ptr_v<Decay>, std::integral_constant<int, 2>, std::integral_constant<int, 0>>>;
578
579 // nope
580 [[nodiscard]] static bool cast(const Box&, Type, Type, void*, std::integral_constant<int, 0>) { return false; }
581
582 // class
583 [[nodiscard]] static bool cast(const Box& self, const Type from, const Type to, void* buffer, std::integral_constant<int, 1>) {
584 if(from.isClass()) {
585 if(const auto ptr = impl::castInternal(self, CeresEngine::getType<T>())) {
586 to.copyConstruct(ptr, buffer);
587 return true;
588 }
589 }
590 return false;
591 }
592
593 // class ptr
594 [[nodiscard]] static bool cast(const Box& self, const Type from, const Type to, void* buffer, std::integral_constant<int, 2>) {
595 if(from.isClassPtr()) {
596 if(const auto ptr = impl::castInternal(self, CeresEngine::getType<T>())) {
597 to.copyConstruct(&ptr, buffer);
598 return true;
599 }
600 }
601 return false;
602 }
603 };
604
605 template<typename T> requires(!std::is_same_v<std::decay_t<T>, Box>)
606 Box::Box(T&& value) {
607 using Type = std::remove_reference_t<T>;
608 const TypeInfo& typeInfo = GetTypeInfo<Type>::get();
609 new(allocate(&typeInfo)) Type(std::forward<T>(value));
610 }
611
612 template<typename T> requires(!std::is_same_v<std::decay_t<T>, Box>)
613 Box& Box::operator=(T&& value) {
614 using Type = std::remove_reference_t<T>;
615 const TypeInfo& typeInfo = GetTypeInfo<Type>::get();
616 new(allocate(&typeInfo)) Type(std::forward<T>(value));
617 return *this;
618 }
619
620 template<typename T> requires(!std::is_same_v<T, Box>) Box::Box(std::reference_wrapper<T> value) {
621 // NOTE: Reference types are cosntructed by storing a raw-pointer to the
622 // type. This is embedded in the semantics of the TypeInfo for
623 // reference types.
624 const TypeInfo& typeInfo = GetTypeInfo<T&>::get();
625 new(allocate(&typeInfo)) T*(&value.get());
626 }
627
628 template<typename T, typename... Args> requires(!std::is_same_v<T, Box>) Box::Box(std::in_place_type_t<T>, Args&&... args) {
629 using Type = std::remove_reference_t<T>;
630 const TypeInfo& typeInfo = GetTypeInfo<Type>::get();
631 new(allocate(&typeInfo)) T(std::forward<Args>(args)...);
632 }
633
634 template<typename T> bool Box::eq(const T& value) const {
635 if(*this == Box{std::cref(value)})
636 return true;
637
640
642 std::aligned_storage_t<sizeof(T), alignof(T)> buffer;
643 if(Type::convert(data(), mt_self, &buffer, mt_value)) {
644 CE_SCOPE_EXIT { reinterpret_cast<T*>(&buffer)->~T(); };
645 return value == *reinterpret_cast<const T*>(&buffer);
646 }
647 }
648
650 auto* buffer = mt_self.allocate();
651 CE_SCOPE_EXIT { mt_self.deallocate(buffer); };
652
653 // Array is passed as **data
654 auto tmp = std::addressof(value);
655 const void* address = tmp;
656 if(mt_value.isArray())
657 address = std::addressof(tmp);
658
659 if(Type::convert(address, mt_value, buffer, mt_self)) {
660 CE_SCOPE_EXIT { mt_self.destroy(buffer); };
661 auto ptr = data();
662 if(mt_self.isArray())
663 ptr = *reinterpret_cast<const void* const*>(ptr);
664 return mt_self.compareEquality(ptr, buffer);
665 }
666 }
667
668 return false;
669 }
670
672 template<typename T> Box box(T& value) { return Box(std::ref(value)); }
673
675 template<typename T> Box box(const T& value) { return Box(std::cref(value)); }
676
678 template<typename T> Box box(T&& value) { return Box(std::forward<T>(value)); }
679
680 // ---------------------------------------------------------------------------------------------
681
682 class Box::Pointer : public Box {
683 using super = Box;
684
685 public:
686 using super::Box;
687
688 CE_EXPLICIT(false) Pointer(const Box& other) : super(other) {}
689 CE_EXPLICIT(false) Pointer(Box&& other) noexcept : super(std::move(other)) {}
690
691 Pointer(const Pointer&) = default;
692 Pointer& operator=(const Pointer&) = default;
693 Pointer(Pointer&&) noexcept = default;
694 Pointer& operator=(Pointer&&) noexcept = default;
695
696 static bool is(const Box& value) noexcept;
697
698 public:
700 [[nodiscard]] Box get() const;
701
703 [[nodiscard]] Box operator*() const;
704
706 [[nodiscard]] Box operator->() const;
707 };
708
709 // ---------------------------------------------------------------------------------------------
710 // ---------------------------------------------------------------------------------------------
711
712 [[nodiscard]] Box dereference(Box&& value);
713 [[nodiscard]] Box dereference(const Box& value);
714
716 template<typename T> [[nodiscard]] Box dereference(Box&& value) { return dereference(std::forward<Box>(value)).ref<T>(); }
717
719 template<typename T> [[nodiscard]] Box dereference(const Box& value) { return dereference(value).ref<T>(); }
720
721 template<> struct GetTypeInfo<Box> {
722 static const TypeInfo& get();
723 };
724
725} // namespace CeresEngine
726
727template<> struct std::hash<CeresEngine::Box> {
728 using BoxType = CeresEngine::Box;
729 [[nodiscard]] std::size_t operator()(const BoxType& value) const noexcept;
730};
#define CE_ASSERT(...)
Definition Macros.hpp:323
#define CE_EXPLICIT(EXPR)
Definition Macros.hpp:413
#define CE_SCOPE_EXIT
Definition ScopeExit.hpp:40
Definition MetaError.hpp:22
Definition MetaError.hpp:23
Definition Box.collection.hpp:86
Definition Box.collection.hpp:55
Definition Box.collection.hpp:14
Definition Box.collection.hpp:269
Definition Box.hpp:682
Pointer(Pointer &&) noexcept=default
Pointer(const Pointer &)=default
Pointer & operator=(const Pointer &)=default
A value type that can hold any alongside it's type information.
Definition Box.hpp:40
bool canConvert(const TypeInfo &target) const
Checks if the value held by the variant is convertible to T.
Type getType() const noexcept
Gets the type held by the variant.
bool isSmall() const noexcept
Determines if the value fits on the small buffer storage.
void * data() noexcept
Returns pointer to decayed type.
Definition Box.hpp:260
void convert()
Converts the variant to type T.
Definition Box.hpp:364
const Class * getClass() const noexcept
friend class Type
Definition Box.hpp:128
bool neq(const T &value) const
Checks if a variant holds the same value as another.
Definition Box.hpp:167
friend bool operator!=(const Box &lhs, const Box &rhs)
Checks if a variant holds the same value as another.
Definition Box.hpp:147
bool is() const
Checks if the value held by the variant is T.
Definition Box.hpp:183
bool canConvert(const TypeID &target) const
Checks if the value held by the variant is convertible to T.
Definition Box.hpp:316
T && ref() &&
Gets the value of the variant as a reference to T.
Definition Box.hpp:229
Pointer asPointer() const &
Views the Box as an Pointer type.
TypeID getTypeID() const noexcept
Gets the ID of the type held by the variant.
Definition Box.hpp:171
Box to(const Type &target) const
Gets the value of the variant as a T.
Definition Box.hpp:351
const TypeInfo * mTypeInfo
The stored value type.
Definition Box.hpp:60
bool empty() const noexcept
Checks if the variant is empty (i.e. holds no value).
void clear() noexcept
Clears the variant and makes it empty.
Box to(const TypeID &target) const
Gets the value of the variant as a T.
Definition Box.hpp:348
~Box() noexcept
Destroys the variant. Will call the contained object destructor.
Box(const void *ptr, const TypeInfo *typeInfo)
static constexpr const size_t kSmallSize
Definition Box.hpp:42
bool tryConvert()
Tries to convert the variant to type T.
Definition Box.hpp:371
void * allocate(const TypeInfo *typeInfo)
void * storage() noexcept
Returns pointer to decayed type.
Definition Box.hpp:406
Type getClassType() const noexcept
Gets the type held by the variant.
ClassInfo getClassInfo() const noexcept
Gets the ClassInfo of the stored value.
T & ref() const &
Gets the value of the variant as a reference to T.
Definition Box.hpp:213
const void * data() const noexcept
Returns pointer to decayed type.
Iterable asIterable() const &
Views the Box as an Iterable type.
const void * storage() const noexcept
Returns pointer to decayed type.
Definition Box.hpp:409
Box rref() &&
Gets a reference to the meta value.
bool eq(const T &value) const
Checks if a variant holds the same value as another.
Definition Box.hpp:634
friend void swap(Box &, Box &) noexcept
Definition Box.hpp:438
bool is(const Type &type) const
Array asArray() const &
Views the Box as an Array type.
Box to(const TypeInfo &target) const
Gets the value of the variant as a T.
friend bool operator==(const Box &lhs, const Box &rhs)
Checks if a variant holds the same value as another.
Box copy() const
Makes a copy of the object.
bool canConvert() const
Checks if the value held by the variant is convertible to T.
Definition Box.hpp:300
Map asMap() const &
Views the Box as an Map type.
const T & cref() const
Gets the value of the variant as a const reference to T.
Definition Box.hpp:237
T to() const &
Gets the value of the variant as a T.
Definition Box.hpp:332
bool canConvert(const Type &target) const
Checks if the value held by the variant is convertible to T.
Definition Box.hpp:319
Box ref() const &
Gets a reference to the meta value.
Storage mStorage
The value storage.
Definition Box.hpp:57
Box() noexcept
Creates a new variant holding an empty value.
Iterator asIterator() const &
Views the Box as an Iterator type.
const Enum * getMetaEnum() const noexcept
TypeID getInternalTypeID(TypeAttribute attr=TypeAttribute::NONE) const noexcept
Gets the type ID for the given type attribute.
T && rref() &&
Gets the value of the variant as a r-value reference to T.
Definition Box.hpp:245
static Box create(Args &&... args)
Definition Box.hpp:118
Definition Class.hpp:46
Represents a reflected enum from C++.
Definition Enum.hpp:26
Definition MetaArgument.hpp:15
Represents a reflected C++ type. Can be used to get metadata from a C++ type.
Definition Type.hpp:32
bool isClassPtr() const noexcept
Returns true if the type is a class pointer, false otherwise.
void * allocate() const
TypeID getDecayTypeID() const noexcept
Gets the decayed type.
const TypeInfo * mTypeInfo
The TypeInfo structure that describes the reflected type.
Definition Type.hpp:35
static bool hasConverter() noexcept
Determines if there is a converter available to convert a value from From to To.
Definition Type.hpp:360
StringView getTypeName() const noexcept
bool isClass() const noexcept
Returns true if the type is a class, false otherwise.
void copyConstruct(const void *source, void *where) const
static bool convert(const void *from, Type fromType, void *to, Type toType)
Definition TypeInfo.hpp:36
const void * castInternal(const Box &self, const Type &type)
constexpr auto is_class_ptr_v
Definition Box.hpp:36
typename is_class_ptr< T >::type is_class_ptr_t
Definition Box.hpp:35
std::conditional_t< std::is_pointer_v< std::remove_reference_t< T > > &&std::is_class_v< std::remove_pointer_t< std::remove_reference_t< T > > >, std::true_type, std::false_type > is_class_ptr
Definition Box.hpp:34
Definition Application.hpp:19
Box box(T &value)
Creates a new Box object by wraping the value as a reference type.
Definition Box.hpp:672
remove_all_cv< std::decay_t< T > > full_decay
Definition TypeTraits.hpp:97
auto dereference(Container &container)
Returns an iterable object that iterates over the values of Container but also dereferences the point...
Definition Iterator.hpp:421
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition Span.hpp:668
Implementation for type casting in Box.
Definition Box.hpp:478
std::remove_pointer_t< Decay > C
Definition Box.hpp:481
std::conditional_t< std::is_class_v< Decay >, std::integral_constant< int, 1 >, std::conditional_t< internal::is_class_ptr_v< Decay >, std::integral_constant< int, 2 >, std::integral_constant< int, 0 > > > tag_t
Definition Box.hpp:483
static const void * cast(const Box &self, const Type from, std::integral_constant< int, 1 >)
Definition Box.hpp:523
static const void * cast(const Box &, Type, std::integral_constant< int, 0 >)
Definition Box.hpp:520
full_decay< T > Decay
Definition Box.hpp:480
static const void * cast(const Box &self, const Type from, std::integral_constant< int, 2 >)
Definition Box.hpp:528
static T * invoke(const Box &self, const TypeID fromID, const TypeID toID)
Definition Box.hpp:486
Implementation for type checks in Box.
Definition Box.hpp:429
Implementation for type conversion in Box.
Definition Box.hpp:546
std::remove_pointer_t< Decay > C
Definition Box.hpp:575
full_decay< T > Decay
Definition Box.hpp:574
static void invoke(const Box &self, const TypeID typeID, void *const buffer)
Definition Box.hpp:549
static bool cast(const Box &, Type, Type, void *, std::integral_constant< int, 0 >)
Definition Box.hpp:580
std::conditional_t< std::is_class_v< Decay >, std::integral_constant< int, 1 >, std::conditional_t< internal::is_class_ptr_v< Decay >, std::integral_constant< int, 2 >, std::integral_constant< int, 0 > > > tag_t
Definition Box.hpp:577
static bool cast(const Box &self, const Type from, const Type to, void *buffer, std::integral_constant< int, 1 >)
Definition Box.hpp:583
static bool cast(const Box &self, const Type from, const Type to, void *buffer, std::integral_constant< int, 2 >)
Definition Box.hpp:594
A structure that contains type information for a class.
Definition IReflectable.hpp:15
static const TypeInfo & get()
A type that contains storage for the Box.
Definition Box.hpp:45
char buffer[kSmallSize]
The buffer to allocate the small object on.
Definition Box.hpp:51
Storage()
Definition Box.hpp:53
void * ptr
The pointer to the object. Only valid if the object is larger than kSmallSize.
Definition Box.hpp:47