@@ -464,6 +464,25 @@ 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+ } else {
474+ return std::unique_ptr<T, D>(raw_ptr);
475+ }
476+ }
477+
478+ template <typename T,
479+ typename D,
480+ typename std::enable_if<!std::is_default_constructible<D>::value, int >::type = 0 >
481+ inline std::unique_ptr<T, D> unique_with_deleter (T *raw_ptr, std::unique_ptr<D> &&deleter) {
482+ assert (deleter != nullptr );
483+ return std::unique_ptr<T, D>(raw_ptr, std::move (*deleter));
484+ }
485+
467486template <typename T>
468487struct smart_holder_type_caster_load {
469488 using holder_type = pybindit::memory::smart_holder;
@@ -589,7 +608,7 @@ struct smart_holder_type_caster_load {
589608 " std::unique_ptr." );
590609 }
591610 if (!have_holder ()) {
592- return nullptr ;
611+ return unique_with_deleter<T, D>( nullptr , std::unique_ptr<D>()) ;
593612 }
594613 throw_if_uninitialized_or_disowned_holder ();
595614 throw_if_instance_is_currently_owned_by_shared_ptr ();
@@ -616,30 +635,21 @@ struct smart_holder_type_caster_load {
616635 " instance cannot safely be transferred to C++." );
617636 }
618637
619- // Default constructed temporary variable to store the extracted deleter in.
620- D extracted_deleter;
638+ // Temporary variable to store the extracted deleter in.
639+ std::unique_ptr<D> extracted_deleter;
621640
622641 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- }
642+ if (gd && gd->use_del_fun ) { // Note the ensure_compatible_rtti_uqp_del<T, D>() call above.
643+ // In smart_holder_poc, a custom deleter is always stored in a guarded delete.
644+ // The guarded delete's std::function<void(void*)> actually points at the
645+ // custom_deleter type, so we can verify it is of the custom deleter type and
646+ // finally extract its deleter.
647+ using custom_deleter_D = pybindit::memory::custom_deleter<T, D>;
648+ const auto &custom_deleter_ptr = gd->del_fun .template target <custom_deleter_D>();
649+ assert (custom_deleter_ptr != nullptr );
650+ // Now that we have confirmed the type of the deleter matches the desired return
651+ // value we can extract the function.
652+ extracted_deleter = std::unique_ptr<D>(new D (std::move (custom_deleter_ptr->deleter )));
643653 }
644654
645655 // Critical transfer-of-ownership section. This must stay together.
@@ -648,7 +658,7 @@ struct smart_holder_type_caster_load {
648658 } else {
649659 holder ().release_ownership ();
650660 }
651- auto result = std::unique_ptr <T, D>(raw_type_ptr, std::move (extracted_deleter));
661+ auto result = unique_with_deleter <T, D>(raw_type_ptr, std::move (extracted_deleter));
652662 if (self_life_support != nullptr ) {
653663 self_life_support->activate_life_support (load_impl.loaded_v_h );
654664 } else {
0 commit comments