| 415 | } // namespace holder_caster_traits_test |
| 416 | |
| 417 | TEST_SUBMODULE(smart_ptr, m) { |
| 418 | // Please do not interleave `struct` and `class` definitions with bindings code, |
| 419 | // but implement `struct`s and `class`es in the anonymous namespace above. |
| 420 | // This helps keeping the smart_holder branch in sync with master. |
| 421 | |
| 422 | // test_smart_ptr |
| 423 | |
| 424 | // Object implementation in `object.h` |
| 425 | py::class_<Object, ref<Object>> obj(m, "Object"); |
| 426 | obj.def("getRefCount", &Object::getRefCount); |
| 427 | |
| 428 | py::class_<MyObject1, ref<MyObject1>>(m, "MyObject1", obj).def(py::init<int>()); |
| 429 | py::implicitly_convertible<py::int_, MyObject1>(); |
| 430 | |
| 431 | m.def("make_object_1", []() -> Object * { return new MyObject1(1); }); |
| 432 | m.def("make_object_2", []() -> ref<Object> { return ref<Object>(new MyObject1(2)); }); |
| 433 | m.def("make_myobject1_1", []() -> MyObject1 * { return new MyObject1(4); }); |
| 434 | m.def("make_myobject1_2", []() -> ref<MyObject1> { return ref<MyObject1>(new MyObject1(5)); }); |
| 435 | m.def("print_object_1", [](const Object *obj) { py::print(obj->toString()); }); |
| 436 | m.def("print_object_2", [](ref<Object> obj) { py::print(obj->toString()); }); |
| 437 | m.def("print_object_3", [](const ref<Object> &obj) { py::print(obj->toString()); }); |
| 438 | m.def("print_object_4", [](const ref<Object> *obj) { py::print((*obj)->toString()); }); |
| 439 | m.def("print_myobject1_1", [](const MyObject1 *obj) { py::print(obj->toString()); }); |
| 440 | m.def("print_myobject1_2", [](ref<MyObject1> obj) { py::print(obj->toString()); }); |
| 441 | m.def("print_myobject1_3", [](const ref<MyObject1> &obj) { py::print(obj->toString()); }); |
| 442 | m.def("print_myobject1_4", [](const ref<MyObject1> *obj) { py::print((*obj)->toString()); }); |
| 443 | |
| 444 | // Expose constructor stats for the ref type |
| 445 | m.def("cstats_ref", &ConstructorStats::get<ref_tag>); |
| 446 | |
| 447 | py::class_<MyObject2, std::shared_ptr<MyObject2>>(m, "MyObject2").def(py::init<int>()); |
| 448 | m.def("make_myobject2_1", []() { return new MyObject2(6); }); |
| 449 | m.def("make_myobject2_2", []() { return std::make_shared<MyObject2>(7); }); |
| 450 | m.def("print_myobject2_1", [](const MyObject2 *obj) { py::print(obj->toString()); }); |
| 451 | // NOLINTNEXTLINE(performance-unnecessary-value-param) |
| 452 | m.def("print_myobject2_2", [](std::shared_ptr<MyObject2> obj) { py::print(obj->toString()); }); |
| 453 | m.def("print_myobject2_3", |
| 454 | [](const std::shared_ptr<MyObject2> &obj) { py::print(obj->toString()); }); |
| 455 | m.def("print_myobject2_4", |
| 456 | [](const std::shared_ptr<MyObject2> *obj) { py::print((*obj)->toString()); }); |
| 457 | |
| 458 | py::class_<MyObject3, std::shared_ptr<MyObject3>>(m, "MyObject3").def(py::init<int>()); |
| 459 | m.def("make_myobject3_1", []() { return new MyObject3(8); }); |
| 460 | m.def("make_myobject3_2", []() { return std::make_shared<MyObject3>(9); }); |
| 461 | m.def("print_myobject3_1", [](const MyObject3 *obj) { py::print(obj->toString()); }); |
| 462 | // NOLINTNEXTLINE(performance-unnecessary-value-param) |
| 463 | m.def("print_myobject3_2", [](std::shared_ptr<MyObject3> obj) { py::print(obj->toString()); }); |
| 464 | m.def("print_myobject3_3", |
| 465 | [](const std::shared_ptr<MyObject3> &obj) { py::print(obj->toString()); }); |
| 466 | m.def("print_myobject3_4", |
| 467 | [](const std::shared_ptr<MyObject3> *obj) { py::print((*obj)->toString()); }); |
| 468 | |
| 469 | // test_smart_ptr_refcounting |
| 470 | m.def("test_object1_refcounting", []() { |
| 471 | auto o = ref<MyObject1>(new MyObject1(0)); |
| 472 | bool good = o->getRefCount() == 1; |
| 473 | py::object o2 = py::cast(o, py::return_value_policy::reference); |
| 474 | // always request (partial) ownership for objects with intrusive |