Same PyObject for a shared_ptr C++ object
I'm not sure I understand all the premises of this question. My kneejerk reaction was, "Would it help if you could assume that C_CLASS derived from std::enable_shared_from_this&lt;C_CLASS&gt;? Is it in your power to make that an invariant in your codebase?" If so, I would even go a step further and ask whether you should just write an enable_PyObject_from_this&lt;C_CLASS&gt; along the same lines.



Anyway, I see a bit of reducible complexity in your code, I think.

template&lt;typename C_CLASS&gt;
using py_ptr = typename boost::python::pointee&lt;boost::shared_ptr&lt;C_CLASS&gt;&gt;::type;


Isn't this just a really complicated way of saying

template&lt;typename T&gt; using py_ptr = T;


(since pointee&lt;ptr&lt;T&gt;&gt;::type is ptr&lt;T&gt;::element_type is T by definition)?  And then you use it in contexts like

template&lt;typename C_CLASS&gt;
PyObject * createObject(const c_sptr&lt;C_CLASS&gt;&amp; obj) {
    return boost::python::objects::make_ptr_instance&lt;py_ptr&lt;C_CLASS&gt;,
            boost::python::objects::pointer_holder&lt;c_sptr&lt;C_CLASS&gt;,
                    py_ptr&lt;C_CLASS&gt;&gt;&gt;::execute(obj);
}


which ought to be more like

template&lt;typename T&gt;
PyObject *createObject(const std::shared_ptr&lt;T&gt;&amp; obj) {
    using namespace boost::python::objects;
    return make_ptr_instance&lt;T, pointer_holder&lt;shared_ptr&lt;T&gt;, T&gt;&gt;::execute(obj);
}


Even that looks more complicated than it feels like it ought to be, but I'm not finding much documentation about what make_ptr_instance is supposed to do (or for that matter why the second template type parameter to pointer_holder isn't defaulted).



I see you use Py_INCREF (all caps) but Py_DecRef (camel case). This suggests to the reader that something really subtle (and thus dangerous) is happening here — or else of course you'd be consistently using Py_IncRef/DecRef or Py_INCREF/DECREF (both of which are provided by the underlying library). But is the reader's inference correct? Are you really doing something subtle and dangerous? Or are you just mixing styles because you felt like it?



Are you at all worried that getCachedObjects&lt;Base&gt;() returns a completely different map from getCachedObjects&lt;Derived&gt;(), even though I might have a std::shared_ptr&lt;Base&gt; b and a std::shared_ptr&lt;Derived&gt; d such that b == d?