20class huge_unique_ptr {
21 std::unique_ptr<T> ptr;
25 explicit huge_unique_ptr(T *p) : ptr(p) {}
26 T *get() {
return ptr.get(); }
31class custom_unique_ptr {
32 std::unique_ptr<T> impl;
35 explicit custom_unique_ptr(T *p) : impl(p) {}
36 T *get()
const {
return impl.get(); }
37 T *release_ptr() {
return impl.release(); }
44class shared_ptr_with_addressof_operator {
45 std::shared_ptr<T> impl;
48 shared_ptr_with_addressof_operator() =
default;
49 explicit shared_ptr_with_addressof_operator(T *p) : impl(p) {}
50 T *get()
const {
return impl.get(); }
51 T **operator&() {
throw std::logic_error(
"Call of overloaded operator& is not expected"); }
58class unique_ptr_with_addressof_operator {
59 std::unique_ptr<T> impl;
62 unique_ptr_with_addressof_operator() =
default;
63 explicit unique_ptr_with_addressof_operator(T *p) : impl(p) {}
64 T *get()
const {
return impl.get(); }
65 T *release_ptr() {
return impl.release(); }
66 T **operator&() {
throw std::logic_error(
"Call of overloaded operator& is not expected"); }
70class MyObject1 :
public Object {
73 std::string
toString()
const override {
return "MyObject1[" + std::to_string(value) +
"]"; }
85 MyObject2(
const MyObject2 &) =
default;
87 std::string
toString()
const {
return "MyObject2[" + std::to_string(value) +
"]"; }
95class MyObject3 :
public std::enable_shared_from_this<MyObject3> {
97 MyObject3(
const MyObject3 &) =
default;
99 std::string
toString()
const {
return "MyObject3[" + std::to_string(value) +
"]"; }
109std::unordered_set<MyObject4 *> myobject4_instances;
112 explicit MyObject4(
int value) :
value{
value} {
114 myobject4_instances.insert(
this);
118 static void cleanupAllInstances() {
119 auto tmp = std::move(myobject4_instances);
120 myobject4_instances.clear();
121 for (
auto *o : tmp) {
128 myobject4_instances.erase(
this);
137std::unordered_set<MyObject4a *> myobject4a_instances;
140 explicit MyObject4a(
int i) :
value{
i} {
142 myobject4a_instances.insert(
this);
146 static void cleanupAllInstances() {
147 auto tmp = std::move(myobject4a_instances);
148 myobject4a_instances.clear();
149 for (
auto *o : tmp) {
155 virtual ~MyObject4a() {
156 myobject4a_instances.erase(
this);
162class MyObject4b :
public MyObject4a {
164 explicit MyObject4b(
int i) : MyObject4a(
i) {
print_created(
this); }
186 std::shared_ptr<A> shared = std::make_shared<A>();
190struct SharedFromThisRef {
191 struct B : std::enable_shared_from_this<B> {
200 std::shared_ptr<B> shared = std::make_shared<B>();
204struct SharedFromThisVBase : std::enable_shared_from_this<SharedFromThisVBase> {
205 SharedFromThisVBase() =
default;
206 SharedFromThisVBase(
const SharedFromThisVBase &) =
default;
207 virtual ~SharedFromThisVBase() =
default;
209struct SharedFromThisVirt :
virtual SharedFromThisVBase {};
218struct TypeForHolderWithAddressOf {
220 TypeForHolderWithAddressOf(
const TypeForHolderWithAddressOf &) {
print_copy_created(
this); }
221 TypeForHolderWithAddressOf(TypeForHolderWithAddressOf &&) noexcept {
226 return "TypeForHolderWithAddressOf[" + std::to_string(value) +
"]";
232struct TypeForMoveOnlyHolderWithAddressOf {
236 return "MoveOnlyHolderWithAddressOf[" + std::to_string(value) +
"]";
242struct HeldByDefaultHolder {};
247 virtual ~ElementBase() =
default;
248 ElementBase() =
default;
249 ElementBase(
const ElementBase &) =
delete;
252struct ElementA : ElementBase {
253 explicit ElementA(
int v) : v(v) {}
254 int value()
const {
return v; }
259 void add(
const std::shared_ptr<ElementBase> &e) { l.push_back(e); }
260 std::vector<std::shared_ptr<ElementBase>> l;
295 py::class_<Object, ref<Object>> obj(m,
"Object");
298 py::class_<MyObject1, ref<MyObject1>>(m,
"MyObject1", obj).def(py::init<int>());
299 py::implicitly_convertible<py::int_, MyObject1>();
301 m.def(
"make_object_1", []() ->
Object * {
return new MyObject1(1); });
303 m.def(
"make_myobject1_1", []() -> MyObject1 * {
return new MyObject1(4); });
305 m.def(
"print_object_1", [](
const Object *obj) { py::print(obj->toString()); });
306 m.def(
"print_object_2", [](
ref<Object> obj) { py::print(obj->toString()); });
307 m.def(
"print_object_3", [](
const ref<Object> &obj) { py::print(obj->toString()); });
308 m.def(
"print_object_4", [](
const ref<Object> *obj) { py::print((*obj)->toString()); });
309 m.def(
"print_myobject1_1", [](
const MyObject1 *obj) { py::print(obj->toString()); });
310 m.def(
"print_myobject1_2", [](
ref<MyObject1> obj) { py::print(obj->toString()); });
311 m.def(
"print_myobject1_3", [](
const ref<MyObject1> &obj) { py::print(obj->toString()); });
312 m.def(
"print_myobject1_4", [](
const ref<MyObject1> *obj) { py::print((*obj)->toString()); });
315 m.def(
"cstats_ref", &ConstructorStats::get<ref_tag>);
317 py::class_<MyObject2, std::shared_ptr<MyObject2>>(m,
"MyObject2").def(py::init<int>());
318 m.def(
"make_myobject2_1", []() {
return new MyObject2(6); });
319 m.def(
"make_myobject2_2", []() {
return std::make_shared<MyObject2>(7); });
320 m.def(
"print_myobject2_1", [](
const MyObject2 *obj) { py::print(obj->toString()); });
322 m.def(
"print_myobject2_2", [](std::shared_ptr<MyObject2> obj) { py::print(obj->toString()); });
323 m.def(
"print_myobject2_3",
324 [](
const std::shared_ptr<MyObject2> &obj) { py::print(obj->toString()); });
325 m.def(
"print_myobject2_4",
326 [](
const std::shared_ptr<MyObject2> *obj) { py::print((*obj)->toString()); });
328 py::class_<MyObject3, std::shared_ptr<MyObject3>>(m,
"MyObject3").def(py::init<int>());
329 m.def(
"make_myobject3_1", []() {
return new MyObject3(8); });
330 m.def(
"make_myobject3_2", []() {
return std::make_shared<MyObject3>(9); });
331 m.def(
"print_myobject3_1", [](
const MyObject3 *obj) { py::print(obj->toString()); });
333 m.def(
"print_myobject3_2", [](std::shared_ptr<MyObject3> obj) { py::print(obj->toString()); });
334 m.def(
"print_myobject3_3",
335 [](
const std::shared_ptr<MyObject3> &obj) { py::print(obj->toString()); });
336 m.def(
"print_myobject3_4",
337 [](
const std::shared_ptr<MyObject3> *obj) { py::print((*obj)->toString()); });
340 m.def(
"test_object1_refcounting", []() {
342 bool good = o->getRefCount() == 1;
343 py::object o2 = py::cast(o, py::return_value_policy::reference);
346 good &= o->getRefCount() == 2;
351 py::class_<MyObject4, std::unique_ptr<MyObject4, py::nodelete>>(m,
"MyObject4")
352 .def(py::init<int>())
353 .def_readwrite(
"value", &MyObject4::value)
354 .def_static(
"cleanup_all_instances", &MyObject4::cleanupAllInstances);
357 py::class_<MyObject4a, std::unique_ptr<MyObject4a, py::nodelete>>(m,
"MyObject4a")
358 .def(py::init<int>())
359 .def_readwrite(
"value", &MyObject4a::value)
360 .def_static(
"cleanup_all_instances", &MyObject4a::cleanupAllInstances);
362 py::class_<MyObject4b, MyObject4a, std::unique_ptr<MyObject4b>>(m,
"MyObject4b")
363 .def(py::init<int>());
366 py::class_<MyObject5, huge_unique_ptr<MyObject5>>(m,
"MyObject5")
367 .def(py::init<int>())
368 .def_readwrite(
"value", &MyObject5::value);
371 using A = SharedPtrRef::A;
372 py::class_<A, std::shared_ptr<A>>(m,
"A");
373 py::class_<SharedPtrRef, std::unique_ptr<SharedPtrRef>>(m,
"SharedPtrRef")
375 .def_readonly(
"ref", &SharedPtrRef::value)
376 .def_property_readonly(
377 "copy", [](
const SharedPtrRef &s) {
return s.value; }, py::return_value_policy::copy)
378 .def_readonly(
"holder_ref", &SharedPtrRef::shared)
379 .def_property_readonly(
381 [](
const SharedPtrRef &s) {
return s.shared; },
382 py::return_value_policy::copy)
383 .def(
"set_ref", [](SharedPtrRef &,
const A &) {
return true; })
385 .def(
"set_holder", [](SharedPtrRef &, std::shared_ptr<A>) {
return true; });
388 using B = SharedFromThisRef::B;
389 py::class_<B, std::shared_ptr<B>>(m,
"B");
390 py::class_<SharedFromThisRef, std::unique_ptr<SharedFromThisRef>>(m,
"SharedFromThisRef")
392 .def_readonly(
"bad_wp", &SharedFromThisRef::value)
393 .def_property_readonly(
"ref",
394 [](
const SharedFromThisRef &s) ->
const B & {
return *s.shared; })
395 .def_property_readonly(
397 [](
const SharedFromThisRef &s) {
return s.value; },
398 py::return_value_policy::copy)
399 .def_readonly(
"holder_ref", &SharedFromThisRef::shared)
400 .def_property_readonly(
402 [](
const SharedFromThisRef &s) {
return s.shared; },
403 py::return_value_policy::copy)
404 .def(
"set_ref", [](SharedFromThisRef &,
const B &) {
return true; })
406 .def(
"set_holder", [](SharedFromThisRef &, std::shared_ptr<B>) {
return true; });
409 static std::shared_ptr<SharedFromThisVirt> sft(
new SharedFromThisVirt());
410 py::class_<SharedFromThisVirt, std::shared_ptr<SharedFromThisVirt>>(m,
"SharedFromThisVirt")
411 .def_static(
"get", []() {
return sft.get(); });
414 py::class_<C, custom_unique_ptr<C>>(m,
"TypeWithMoveOnlyHolder")
415 .def_static(
"make", []() {
return custom_unique_ptr<C>(
new C); })
416 .def_static(
"make_as_object", []() {
return py::cast(custom_unique_ptr<C>(
new C)); });
419 using HolderWithAddressOf = shared_ptr_with_addressof_operator<TypeForHolderWithAddressOf>;
420 py::class_<TypeForHolderWithAddressOf, HolderWithAddressOf>(m,
"TypeForHolderWithAddressOf")
421 .def_static(
"make", []() {
return HolderWithAddressOf(
new TypeForHolderWithAddressOf); })
422 .def(
"get", [](
const HolderWithAddressOf &
self) {
return self.get(); })
423 .def(
"print_object_1",
424 [](
const TypeForHolderWithAddressOf *obj) { py::print(obj->toString()); })
426 .def(
"print_object_2", [](HolderWithAddressOf obj) { py::print(obj.get()->toString()); })
427 .def(
"print_object_3",
428 [](
const HolderWithAddressOf &obj) { py::print(obj.get()->toString()); })
429 .def(
"print_object_4",
430 [](
const HolderWithAddressOf *obj) { py::print((*obj).get()->toString()); });
433 using MoveOnlyHolderWithAddressOf
434 = unique_ptr_with_addressof_operator<TypeForMoveOnlyHolderWithAddressOf>;
435 py::class_<TypeForMoveOnlyHolderWithAddressOf, MoveOnlyHolderWithAddressOf>(
436 m,
"TypeForMoveOnlyHolderWithAddressOf")
439 return MoveOnlyHolderWithAddressOf(
440 new TypeForMoveOnlyHolderWithAddressOf(0));
442 .def_readwrite(
"value", &TypeForMoveOnlyHolderWithAddressOf::value)
444 [](
const TypeForMoveOnlyHolderWithAddressOf *obj) { py::print(obj->toString()); });
447 py::class_<HeldByDefaultHolder, std::unique_ptr<HeldByDefaultHolder>>(m,
"HeldByDefaultHolder")
450 .def_static(
"load_shared_ptr", [](std::shared_ptr<HeldByDefaultHolder>) {});
454 py::class_<ElementBase, std::shared_ptr<ElementBase>>(m,
"ElementBase");
456 py::class_<ElementA, ElementBase, std::shared_ptr<ElementA>>(m,
"ElementA")
457 .def(py::init<int>())
458 .def(
"value", &ElementA::value);
460 py::class_<ElementList, std::shared_ptr<ElementList>>(m,
"ElementList")
462 .def(
"add", &ElementList::add)
463 .def(
"get", [](ElementList &el) {
465 for (
auto &e : el.l) {
Reference counted object base class.
int getRefCount() const
Return the current reference count.
virtual std::string toString() const =0
Reference counting helper.
T * get_ptr()
Return a const pointer to the referenced object.
std::string toString(const URI &aURI)
#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type,...)
Create a specialization for custom holder types (silently ignores std::shared_ptr)
void print_copy_created(T *inst, Values &&...values)
void print_created(T *inst, Values &&...values)
void print_destroyed(T *inst, Values &&...values)
void print_move_created(T *inst, Values &&...values)
#define TEST_SUBMODULE(name, variable)
static const T * get(const ref< T > &p)
Helper class which abstracts away certain actions.