|
| 1 | +#include "zoo/Any/VTablePolicy.h" |
| 2 | +#include "zoo/AnyContainer.h" |
| 3 | + |
| 4 | +#include <memory> // for shared pointer |
| 5 | + |
| 6 | +namespace user { |
| 7 | + |
| 8 | +struct ExplicitDestructor { |
| 9 | + static inline void *last = nullptr; |
| 10 | + |
| 11 | + ~ExplicitDestructor() { last = this; } |
| 12 | +}; |
| 13 | + |
| 14 | +template<typename> |
| 15 | +struct SharedPointerOptIn: std::false_type {}; |
| 16 | +template<> |
| 17 | +struct SharedPointerOptIn<int>: std::true_type {}; |
| 18 | +template<> |
| 19 | +struct SharedPointerOptIn<ExplicitDestructor>: std::true_type {}; |
| 20 | + |
| 21 | +template<typename HoldingModel, typename... AffordanceSpecifications> |
| 22 | +struct UserValueManagement { |
| 23 | + /// abbreviation |
| 24 | + using GP = |
| 25 | + typename zoo::GenericPolicy<HoldingModel, AffordanceSpecifications...>; |
| 26 | + |
| 27 | + template<typename V> |
| 28 | + struct SharedPointerManager: |
| 29 | + // Inherit for compatibility with the Generic Policy framework |
| 30 | + GP::Container |
| 31 | + { |
| 32 | + /// Abbreviation |
| 33 | + using Base = typename GP::Container; |
| 34 | + /// ManagedType is necessary for the affordances |
| 35 | + using ManagedType = V; |
| 36 | + /// Helper for this particular type of manager, VP for "Value Pointer" |
| 37 | + using VP = std::shared_ptr<V>; |
| 38 | + /// Abbreviation |
| 39 | + using SPM = SharedPointerManager; |
| 40 | + |
| 41 | + |
| 42 | + VP *sharedPointer() noexcept { return this->space_.template as<VP>(); } |
| 43 | + V *value() noexcept { return &**sharedPointer(); } |
| 44 | + |
| 45 | + const V *value() const noexcept { |
| 46 | + return const_cast<SPM *>(this)->value(); |
| 47 | + } |
| 48 | + |
| 49 | + static void destructor(void *p) noexcept { |
| 50 | + auto sPtr = static_cast<SPM *>(p); |
| 51 | + sPtr->sharedPointer()->~VP(); |
| 52 | + } |
| 53 | + |
| 54 | + static void move(void *to, void *from) noexcept { |
| 55 | + auto downcast = static_cast<SPM *>(from); |
| 56 | + new(to) SPM(std::move(*downcast)); |
| 57 | + } |
| 58 | + |
| 59 | + static void copyOp(void *to, const void *from) { |
| 60 | + auto downcast = static_cast<const SPM *>(from); |
| 61 | + new(to) SPM(*downcast); |
| 62 | + } |
| 63 | + |
| 64 | + constexpr static inline typename GP::VTable Operations = { |
| 65 | + AffordanceSpecifications::template Operation<SPM>... |
| 66 | + }; |
| 67 | + |
| 68 | + SharedPointerManager(SharedPointerManager &&donor) noexcept: |
| 69 | + Base(&Operations) |
| 70 | + { |
| 71 | + new(sharedPointer()) VP(std::move(*donor.sharedPointer())); |
| 72 | + } |
| 73 | + |
| 74 | + SharedPointerManager(const SharedPointerManager &donor) noexcept: |
| 75 | + Base(&Operations) |
| 76 | + { |
| 77 | + new(sharedPointer()) VP(*const_cast<SPM &>(donor).sharedPointer()); |
| 78 | + } |
| 79 | + |
| 80 | + |
| 81 | + template<typename... Args> |
| 82 | + SharedPointerManager(Args &&...args): |
| 83 | + Base(&Operations) |
| 84 | + { |
| 85 | + new(sharedPointer()) |
| 86 | + VP(std::make_shared<V>(std::forward<Args>(args)...)); |
| 87 | + } |
| 88 | + |
| 89 | + using IsReferenceTrait = std::false_type; |
| 90 | + constexpr static inline auto IsReference = IsReferenceTrait::value; |
| 91 | + }; |
| 92 | + |
| 93 | + struct AdaptedPolicy: GP::Policy { |
| 94 | + template<typename V> |
| 95 | + using Builder = |
| 96 | + std::conditional_t< |
| 97 | + SharedPointerOptIn<V>::value, |
| 98 | + SharedPointerManager<V>, |
| 99 | + typename GP::Policy::template Builder<V> |
| 100 | + >; |
| 101 | + }; |
| 102 | +}; |
| 103 | + |
| 104 | +template<typename H, typename... Afs> |
| 105 | +using SharedPointerPolicy = |
| 106 | + typename UserValueManagement<H, Afs...>::AdaptedPolicy; |
| 107 | + |
| 108 | +} |
0 commit comments