fix: add support for const-only smart pointers (#5718)

* add support for const pointers in smart pointers

* use c++11 compatible code

* add template parameter in test

* Make the const-removal clearly visible. This simplifies the production code changes significantly.

For background see: https://claude.ai/share/4085d9ab-a859-44cc-bb56-450e472f817a

* test without leaks

* add namespace for test

* rename test

* fix test compilation

* using namespace test_const_only_smart_ptr;

* fix smartptr in test

* smaller test body

* move test

* style: pre-commit fixes

---------

Co-authored-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Rosdf
2025-06-11 20:32:26 +04:00
committed by GitHub
parent 513d1f962e
commit 7ed76e2d50
3 changed files with 35 additions and 3 deletions

View File

@@ -69,6 +69,20 @@ public:
T **operator&() { throw std::logic_error("Call of overloaded operator& is not expected"); }
};
// Simple custom holder that imitates smart pointer, that always stores cpointer to const
template <class T>
class const_only_shared_ptr {
std::shared_ptr<const T> ptr_;
public:
const_only_shared_ptr() = default;
explicit const_only_shared_ptr(const T *ptr) : ptr_(ptr) {}
const T *get() const { return ptr_.get(); }
private:
// for demonstration purpose only, this imitates smart pointer with a const-only pointer
};
// Custom object with builtin reference counting (see 'object.h' for the implementation)
class MyObject1 : public Object {
public:
@@ -283,6 +297,7 @@ struct holder_helper<ref<T>> {
// Make pybind aware of the ref-counted wrapper type (s):
PYBIND11_DECLARE_HOLDER_TYPE(T, ref<T>, true)
PYBIND11_DECLARE_HOLDER_TYPE(T, const_only_shared_ptr<T>, true)
// The following is not required anymore for std::shared_ptr, but it should compile without error:
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)
PYBIND11_DECLARE_HOLDER_TYPE(T, huge_unique_ptr<T>)
@@ -397,6 +412,11 @@ TEST_SUBMODULE(smart_ptr, m) {
m.def("print_myobject2_4",
[](const std::shared_ptr<MyObject2> *obj) { py::print((*obj)->toString()); });
m.def("make_myobject2_3",
[](int val) { return const_only_shared_ptr<MyObject2>(new MyObject2(val)); });
m.def("print_myobject2_5",
[](const const_only_shared_ptr<MyObject2> &obj) { py::print(obj.get()->toString()); });
py::class_<MyObject3, std::shared_ptr<MyObject3>>(m, "MyObject3").def(py::init<int>());
m.def("make_myobject3_1", []() { return new MyObject3(8); });
m.def("make_myobject3_2", []() { return std::make_shared<MyObject3>(9); });