Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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_OBJECTS:Catch2Main>)
target_link_libraries(algorithm2 AlgorithmTest)
Expand Down
46 changes: 46 additions & 0 deletions test/demo/type_erasure_shared_pointer_value_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "demo/type_erasure_shared_pointer_value_manager.hpp"

#include "zoo/FunctionPolicy.h"

#include <catch2/catch.hpp>

namespace user {

template<typename V, typename Policy>
auto extractSharedPointer(zoo::AnyContainer<Policy> &a) {
using VBuilder = typename Policy::template Builder<V>;
auto downcasted = static_cast<VBuilder *>(a.container());
return downcasted->sharedPointer();
}

}

using LocalBuffer = void *[4];
static_assert(sizeof(std::shared_ptr<int>) <= 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<double>());
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<user::ExplicitDestructor>(uAny);
auto sp = *spp;
REQUIRE(2 == sp.use_count());
CHECK(nullptr == user::ExplicitDestructor::last);
const auto oldAddress = uAny.state<user::ExplicitDestructor>();
REQUIRE(oldAddress == &*sp);
sp.reset();
REQUIRE(1 == spp->use_count());
uAny = 5;
REQUIRE(oldAddress == user::ExplicitDestructor::last);
}
108 changes: 108 additions & 0 deletions test/inc/demo/type_erasure_shared_pointer_value_manager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include "zoo/Any/VTablePolicy.h"
#include "zoo/AnyContainer.h"

#include <memory> // for shared pointer

namespace user {

struct ExplicitDestructor {
static inline void *last = nullptr;

~ExplicitDestructor() { last = this; }
};

template<typename>
struct SharedPointerOptIn: std::false_type {};
template<>
struct SharedPointerOptIn<int>: std::true_type {};
template<>
struct SharedPointerOptIn<ExplicitDestructor>: std::true_type {};

template<typename HoldingModel, typename... AffordanceSpecifications>
struct UserValueManagement {
/// abbreviation
using GP =
typename zoo::GenericPolicy<HoldingModel, AffordanceSpecifications...>;

template<typename V>
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<V>;
/// Abbreviation
using SPM = SharedPointerManager;


VP *sharedPointer() noexcept { return this->space_.template as<VP>(); }
V *value() noexcept { return &**sharedPointer(); }

const V *value() const noexcept {
return const_cast<SPM *>(this)->value();
}

static void destructor(void *p) noexcept {
auto sPtr = static_cast<SPM *>(p);
sPtr->sharedPointer()->~VP();
}

static void move(void *to, void *from) noexcept {
auto downcast = static_cast<SPM *>(from);
new(to) SPM(std::move(*downcast));
}

static void copyOp(void *to, const void *from) {
auto downcast = static_cast<const SPM *>(from);
new(to) SPM(*downcast);
}

constexpr static inline typename GP::VTable Operations = {
AffordanceSpecifications::template Operation<SPM>...
};

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<SPM &>(donor).sharedPointer());
}


template<typename... Args>
SharedPointerManager(Args &&...args):
Base(&Operations)
{
new(sharedPointer())
VP(std::make_shared<V>(std::forward<Args>(args)...));
}

using IsReferenceTrait = std::false_type;
constexpr static inline auto IsReference = IsReferenceTrait::value;
};

struct AdaptedPolicy: GP::Policy {
template<typename V>
using Builder =
std::conditional_t<
SharedPointerOptIn<V>::value,
SharedPointerManager<V>,
typename GP::Policy::template Builder<V>
>;
};
};

template<typename H, typename... Afs>
using SharedPointerPolicy =
typename UserValueManagement<H, Afs...>::AdaptedPolicy;

}