Interaction with custom holder types
pybind11 has the notion of a "custom holder type" that allows declaring a non-::std wrapper type for types passed to and from python from C++.
https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html#custom-smart-pointers
Has there been any activity on supporting a feature like this for cxx?
For fun I started looking at how hard it would be to create rust bindings for the SerenityOS set of libraries, and pretty much immediately ran into the problem that all reference-counted types use a custom intrusive reference count CRTP pattern.
i.e., the custom AK::RefPtr type knows how to call T::ref() and T::unref(), while the reference count and actual implementation happens in class Foo : public RefCounted<Foo>.
The only way that makes sense to me to bind this category of types as I start looking into this is to introduce a wrapper type that owns a RefPtr to the type in question, and then expose a factory function to create a unique_ptr<FooWrapper>, like so in a shim header:
class Foo; // Actual C++ type I wanted to bind
class FooWrapper
{
public:
explicit FooWrapper(NonnullRefPtr<Foo> impl) : m_impl(std::move(impl)) {}
Foo& pin_mut() { return *m_impl; }
Foo const& pin() const { return *m_impl; }
private:
NonnullRefPtr<Foo> m_impl;
};
inline std:;unique_ptr<FooWrapper> create_foo(FooCtorArgs args)
{
return std::make_unique<FooWrapper>(make_ref_counted<Foo>(std::move(args)));
}
This adds an unfortunate level of indirection, and an extra heap allocation for my types.
Is there another, more obvious way to solve this problem?
I suspect that copy + paste of the SharedPtr<T> implementation with the type names changed to my custom reference counted pointer type would get me 90% of the way there, but surely there's other folks who are trying to do similar things?