Skip to content

Commit 2ddd965

Browse files
authored
Merge pull request #109 from thecppzoo/em/shared-pointer
Demo of shared pointer value manager for AnyContainer
2 parents c25b849 + ae6b550 commit 2ddd965

File tree

3 files changed

+159
-1
lines changed

3 files changed

+159
-1
lines changed

test/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ else()
124124
set(
125125
MISCELLANEA_SOURCES
126126
egyptian.cpp var.cpp variant.cpp CopyMoveAbilities.cpp root/mem.cpp
127+
demo/type_erasure_shared_pointer_value_manager.cpp
127128
)
128129
set(
129130
ZOO_TEST_SOURCES
@@ -142,7 +143,10 @@ else()
142143
add_executable(
143144
${CURRENT_EXECUTABLE} ${ADDITIONAL_SOURCES}
144145
)
145-
target_link_libraries(${CURRENT_EXECUTABLE} Catch2Main AlgorithmTest TypeErasureTest SWARTest Uncategorized)
146+
target_link_libraries(
147+
${CURRENT_EXECUTABLE}
148+
Catch2Main AlgorithmTest TypeErasureTest SWARTest Uncategorized
149+
)
146150

147151
add_executable(algorithm2 $<TARGET_OBJECTS:Catch2Main>)
148152
target_link_libraries(algorithm2 AlgorithmTest)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "demo/type_erasure_shared_pointer_value_manager.hpp"
2+
3+
#include "zoo/FunctionPolicy.h"
4+
5+
#include <catch2/catch.hpp>
6+
7+
namespace user {
8+
9+
template<typename V, typename Policy>
10+
auto extractSharedPointer(zoo::AnyContainer<Policy> &a) {
11+
using VBuilder = typename Policy::template Builder<V>;
12+
auto downcasted = static_cast<VBuilder *>(a.container());
13+
return downcasted->sharedPointer();
14+
}
15+
16+
}
17+
18+
using LocalBuffer = void *[4];
19+
static_assert(sizeof(std::shared_ptr<int>) <= sizeof(LocalBuffer));
20+
21+
using UAny = zoo::AnyContainer<
22+
user::SharedPointerPolicy<
23+
LocalBuffer,
24+
zoo::Destroy, zoo::Move, zoo::Copy, zoo::RTTI
25+
>
26+
>;
27+
28+
TEST_CASE("Shared Pointer Value Manager", "[demo][type-erasure][shared-pointer-policy]") {
29+
UAny uAny{9.9};
30+
CHECK(9.9 == *uAny.state<double>());
31+
user::ExplicitDestructor ed;
32+
REQUIRE(nullptr == user::ExplicitDestructor::last);
33+
uAny = ed;
34+
CHECK(nullptr == user::ExplicitDestructor::last);
35+
REQUIRE(typeid(user::ExplicitDestructor) == uAny.type());
36+
auto spp = user::extractSharedPointer<user::ExplicitDestructor>(uAny);
37+
auto sp = *spp;
38+
REQUIRE(2 == sp.use_count());
39+
CHECK(nullptr == user::ExplicitDestructor::last);
40+
const auto oldAddress = uAny.state<user::ExplicitDestructor>();
41+
REQUIRE(oldAddress == &*sp);
42+
sp.reset();
43+
REQUIRE(1 == spp->use_count());
44+
uAny = 5;
45+
REQUIRE(oldAddress == user::ExplicitDestructor::last);
46+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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

Comments
 (0)