@@ -464,6 +464,25 @@ struct shared_ptr_trampoline_self_life_support {
464
464
}
465
465
};
466
466
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
+
467
486
template <typename T>
468
487
struct smart_holder_type_caster_load {
469
488
using holder_type = pybindit::memory::smart_holder;
@@ -589,7 +608,7 @@ struct smart_holder_type_caster_load {
589
608
" std::unique_ptr." );
590
609
}
591
610
if (!have_holder ()) {
592
- return nullptr ;
611
+ return unique_with_deleter<T, D>( nullptr , std::unique_ptr<D>()) ;
593
612
}
594
613
throw_if_uninitialized_or_disowned_holder ();
595
614
throw_if_instance_is_currently_owned_by_shared_ptr ();
@@ -616,30 +635,21 @@ struct smart_holder_type_caster_load {
616
635
" instance cannot safely be transferred to C++." );
617
636
}
618
637
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;
621
640
622
641
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::make_unique<D>(std::move (custom_deleter_ptr->deleter ));
643
653
}
644
654
645
655
// Critical transfer-of-ownership section. This must stay together.
@@ -648,7 +658,7 @@ struct smart_holder_type_caster_load {
648
658
} else {
649
659
holder ().release_ownership ();
650
660
}
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));
652
662
if (self_life_support != nullptr ) {
653
663
self_life_support->activate_life_support (load_impl.loaded_v_h );
654
664
} else {
0 commit comments