@@ -1563,6 +1563,9 @@ struct copyable_holder_caster : public type_caster_base<type> {
15631563 throw cast_error (" Unable to load a custom holder type from a default-holder instance" );
15641564 }
15651565
1566+ // holders that are not std::shared_ptr
1567+ template <typename T = holder_type,
1568+ detail::enable_if_t <!is_shared_ptr<T>::value, int > = 0 >
15661569 bool load_value (value_and_holder &&v_h) {
15671570 if (v_h.holder_constructed ()) {
15681571 value = v_h.value_ptr ();
@@ -1578,6 +1581,34 @@ struct copyable_holder_caster : public type_caster_base<type> {
15781581 }
15791582 }
15801583
1584+ // holders that are std::shared_ptr
1585+ template <typename T = holder_type,
1586+ detail::enable_if_t <is_shared_ptr<T>::value, int > = 0 >
1587+ bool load_value (value_and_holder &&v_h) {
1588+ if (v_h.holder_constructed ()) {
1589+ value = v_h.value_ptr ();
1590+
1591+ // The shared_ptr is always given to C++ code, so we construct a new shared_ptr
1592+ // that is given a custom deleter. The custom deleter increments the python
1593+ // reference count to bind the python instance lifetime with the lifetime
1594+ // of the shared_ptr.
1595+ //
1596+ // This enables things like passing the last python reference of a subclass to a
1597+ // C++ function without the python reference dying.
1598+ //
1599+ // Reference cycles will cause a leak, but this is a limitation of shared_ptr
1600+ holder = holder_type ((type*)value, [unused = reinterpret_borrow<object>((PyObject*)v_h.inst )](type*){});
1601+ return true ;
1602+ } else {
1603+ throw cast_error (" Unable to cast from non-held to held instance (T& to Holder<T>) "
1604+ #if defined(NDEBUG)
1605+ " (compile in debug mode for type information)" );
1606+ #else
1607+ " of type '" + type_id<holder_type>() + " ''" );
1608+ #endif
1609+ }
1610+ }
1611+
15811612 template <typename T = holder_type, detail::enable_if_t <!std::is_constructible<T, const T &, type*>::value, int > = 0 >
15821613 bool try_implicit_casts (handle, bool ) { return false ; }
15831614
0 commit comments