diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b4b4050e..ef981efc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -124,6 +124,7 @@ else() set( MISCELLANEA_SOURCES egyptian.cpp var.cpp variant.cpp CopyMoveAbilities.cpp root/mem.cpp + demo/type_erasure_shared_pointer_value_manager.cpp ) set( ZOO_TEST_SOURCES @@ -142,7 +143,10 @@ else() add_executable( ${CURRENT_EXECUTABLE} ${ADDITIONAL_SOURCES} ) - target_link_libraries(${CURRENT_EXECUTABLE} Catch2Main AlgorithmTest TypeErasureTest SWARTest Uncategorized) + target_link_libraries( + ${CURRENT_EXECUTABLE} + Catch2Main AlgorithmTest TypeErasureTest SWARTest Uncategorized + ) add_executable(algorithm2 $) target_link_libraries(algorithm2 AlgorithmTest) diff --git a/test/demo/type_erasure_shared_pointer_value_manager.cpp b/test/demo/type_erasure_shared_pointer_value_manager.cpp new file mode 100644 index 00000000..a8459dbb --- /dev/null +++ b/test/demo/type_erasure_shared_pointer_value_manager.cpp @@ -0,0 +1,46 @@ +#include "demo/type_erasure_shared_pointer_value_manager.hpp" + +#include "zoo/FunctionPolicy.h" + +#include + +namespace user { + +template +auto extractSharedPointer(zoo::AnyContainer &a) { + using VBuilder = typename Policy::template Builder; + auto downcasted = static_cast(a.container()); + return downcasted->sharedPointer(); +} + +} + +using LocalBuffer = void *[4]; +static_assert(sizeof(std::shared_ptr) <= sizeof(LocalBuffer)); + +using UAny = zoo::AnyContainer< + user::SharedPointerPolicy< + LocalBuffer, + zoo::Destroy, zoo::Move, zoo::Copy, zoo::RTTI + > +>; + +TEST_CASE("Shared Pointer Value Manager", "[demo][type-erasure][shared-pointer-policy]") { + UAny uAny{9.9}; + CHECK(9.9 == *uAny.state()); + user::ExplicitDestructor ed; + REQUIRE(nullptr == user::ExplicitDestructor::last); + uAny = ed; + CHECK(nullptr == user::ExplicitDestructor::last); + REQUIRE(typeid(user::ExplicitDestructor) == uAny.type()); + auto spp = user::extractSharedPointer(uAny); + auto sp = *spp; + REQUIRE(2 == sp.use_count()); + CHECK(nullptr == user::ExplicitDestructor::last); + const auto oldAddress = uAny.state(); + REQUIRE(oldAddress == &*sp); + sp.reset(); + REQUIRE(1 == spp->use_count()); + uAny = 5; + REQUIRE(oldAddress == user::ExplicitDestructor::last); +} diff --git a/test/inc/demo/type_erasure_shared_pointer_value_manager.hpp b/test/inc/demo/type_erasure_shared_pointer_value_manager.hpp new file mode 100644 index 00000000..d7b0760a --- /dev/null +++ b/test/inc/demo/type_erasure_shared_pointer_value_manager.hpp @@ -0,0 +1,108 @@ +#include "zoo/Any/VTablePolicy.h" +#include "zoo/AnyContainer.h" + +#include // for shared pointer + +namespace user { + +struct ExplicitDestructor { + static inline void *last = nullptr; + + ~ExplicitDestructor() { last = this; } +}; + +template +struct SharedPointerOptIn: std::false_type {}; +template<> +struct SharedPointerOptIn: std::true_type {}; +template<> +struct SharedPointerOptIn: std::true_type {}; + +template +struct UserValueManagement { + /// abbreviation + using GP = + typename zoo::GenericPolicy; + + template + struct SharedPointerManager: + // Inherit for compatibility with the Generic Policy framework + GP::Container + { + /// Abbreviation + using Base = typename GP::Container; + /// ManagedType is necessary for the affordances + using ManagedType = V; + /// Helper for this particular type of manager, VP for "Value Pointer" + using VP = std::shared_ptr; + /// Abbreviation + using SPM = SharedPointerManager; + + + VP *sharedPointer() noexcept { return this->space_.template as(); } + V *value() noexcept { return &**sharedPointer(); } + + const V *value() const noexcept { + return const_cast(this)->value(); + } + + static void destructor(void *p) noexcept { + auto sPtr = static_cast(p); + sPtr->sharedPointer()->~VP(); + } + + static void move(void *to, void *from) noexcept { + auto downcast = static_cast(from); + new(to) SPM(std::move(*downcast)); + } + + static void copyOp(void *to, const void *from) { + auto downcast = static_cast(from); + new(to) SPM(*downcast); + } + + constexpr static inline typename GP::VTable Operations = { + AffordanceSpecifications::template Operation... + }; + + SharedPointerManager(SharedPointerManager &&donor) noexcept: + Base(&Operations) + { + new(sharedPointer()) VP(std::move(*donor.sharedPointer())); + } + + SharedPointerManager(const SharedPointerManager &donor) noexcept: + Base(&Operations) + { + new(sharedPointer()) VP(*const_cast(donor).sharedPointer()); + } + + + template + SharedPointerManager(Args &&...args): + Base(&Operations) + { + new(sharedPointer()) + VP(std::make_shared(std::forward(args)...)); + } + + using IsReferenceTrait = std::false_type; + constexpr static inline auto IsReference = IsReferenceTrait::value; + }; + + struct AdaptedPolicy: GP::Policy { + template + using Builder = + std::conditional_t< + SharedPointerOptIn::value, + SharedPointerManager, + typename GP::Policy::template Builder + >; + }; +}; + +template +using SharedPointerPolicy = + typename UserValueManagement::AdaptedPolicy; + +}