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