@@ -464,6 +464,24 @@ struct shared_ptr_trampoline_self_life_support {
464464 }
465465};
466466
467+ template <typename T,
468+ typename D,
469+ typename std::enable_if<std::is_default_constructible<D>::value, int >::type = 0 >
470+ inline std::unique_ptr<T, D> unique_with_deleter (T *raw_ptr, std::unique_ptr<D> &&deleter) {
471+ if (deleter != nullptr ) {
472+ return std::unique_ptr<T, D>(raw_ptr, std::move (*deleter));
473+ }
474+ return std::unique_ptr<T, D>(raw_ptr);
475+ }
476+
477+ template <typename T,
478+ typename D,
479+ typename std::enable_if<!std::is_default_constructible<D>::value, int >::type = 0 >
480+ inline std::unique_ptr<T, D> unique_with_deleter (T *raw_ptr, std::unique_ptr<D> &&deleter) {
481+ assert (deleter != nullptr );
482+ return std::unique_ptr<T, D>(raw_ptr, std::move (*deleter));
483+ }
484+
467485template <typename T>
468486struct smart_holder_type_caster_load {
469487 using holder_type = pybindit::memory::smart_holder;
@@ -589,7 +607,7 @@ struct smart_holder_type_caster_load {
589607 " std::unique_ptr." );
590608 }
591609 if (!have_holder ()) {
592- return nullptr ;
610+ return unique_with_deleter<T, D>( nullptr , std::unique_ptr<D>()) ;
593611 }
594612 throw_if_uninitialized_or_disowned_holder ();
595613 throw_if_instance_is_currently_owned_by_shared_ptr ();
@@ -616,30 +634,21 @@ struct smart_holder_type_caster_load {
616634 " instance cannot safely be transferred to C++." );
617635 }
618636
619- // Default constructed temporary variable to store the extracted deleter in.
620- D extracted_deleter;
637+ // Temporary variable to store the extracted deleter in.
638+ std::unique_ptr<D> extracted_deleter;
621639
622640 auto *gd = std::get_deleter<pybindit::memory::guarded_delete>(holder ().vptr );
623- if (gd) {
624- if (gd->use_del_fun ) {
625- // In smart_holder_poc, a custom deleter is always stored in a guarded delete.
626- // The guarded delete's std::function<void(void*)> actually points at the
627- // custom_deleter type, so we can verify it is of the custom deleter type and
628- // finally extract its deleter.
629- using custom_deleter_D = pybindit::memory::custom_deleter<T, D>;
630- const auto &custom_deleter_ptr = gd->del_fun .template target <custom_deleter_D>();
631- if (!custom_deleter_ptr) {
632- throw cast_error (" Deletion function is not stored in custom deleter, cannot \
633- extract the deleter correctly." );
634- }
635- // Now that we have confirmed the type of the deleter matches the desired return
636- // value we can extract the function.
637- extracted_deleter = std::move (custom_deleter_ptr->deleter );
638- } else {
639- // Not sure if anything needs to be done here. In general, if the del function is
640- // used a default destructor is used which should be accommodated by the type of
641- // the deleter used in the returned unique ptr.
642- }
641+ if (gd && gd->use_del_fun ) { // Note the ensure_compatible_rtti_uqp_del<T, D>() call above.
642+ // In smart_holder_poc, a custom deleter is always stored in a guarded delete.
643+ // The guarded delete's std::function<void(void*)> actually points at the
644+ // custom_deleter type, so we can verify it is of the custom deleter type and
645+ // finally extract its deleter.
646+ using custom_deleter_D = pybindit::memory::custom_deleter<T, D>;
647+ const auto &custom_deleter_ptr = gd->del_fun .template target <custom_deleter_D>();
648+ assert (custom_deleter_ptr != nullptr );
649+ // Now that we have confirmed the type of the deleter matches the desired return
650+ // value we can extract the function.
651+ extracted_deleter = std::unique_ptr<D>(new D (std::move (custom_deleter_ptr->deleter )));
643652 }
644653
645654 // Critical transfer-of-ownership section. This must stay together.
@@ -648,7 +657,7 @@ struct smart_holder_type_caster_load {
648657 } else {
649658 holder ().release_ownership ();
650659 }
651- auto result = std::unique_ptr <T, D>(raw_type_ptr, std::move (extracted_deleter));
660+ auto result = unique_with_deleter <T, D>(raw_type_ptr, std::move (extracted_deleter));
652661 if (self_life_support != nullptr ) {
653662 self_life_support->activate_life_support (load_impl.loaded_v_h );
654663 } else {
0 commit comments