@@ -68,6 +68,22 @@ static constexpr bool type_has_shared_from_this(const std::enable_shared_from_th
68
68
return true ;
69
69
}
70
70
71
+ namespace detail {
72
+ template <typename D, bool > struct delete_assigner {
73
+ static void assign (D&, bool , std::function<void (void *)>&, void(*)(void *)&){}
74
+ };
75
+
76
+ template <typename D> struct delete_assigner <D, true > {
77
+ static void assign (D& deleter, bool use_del_fun, std::function<void (void *)>& del_fun, void(*del_ptr)(void *)&){
78
+ if (use_del_fun) {
79
+ deleter = std::move (del_fun);
80
+ } else {
81
+ deleter = del_ptr;
82
+ }
83
+ }
84
+ };
85
+ }
86
+
71
87
struct guarded_delete {
72
88
std::weak_ptr<void > released_ptr; // Trick to keep the smart_holder memory footprint small.
73
89
std::function<void (void *)> del_fun; // Rare case.
@@ -88,6 +104,15 @@ struct guarded_delete {
88
104
}
89
105
}
90
106
}
107
+
108
+ template <typename T, typename D>
109
+ bool extract_deleter (D& deleter) {
110
+ if (armed_flag) {
111
+ detail::delete_assigner<D, std::is_same<D, decltype (del_fun)>::value>::assign (deleter, use_del_fun, del_fun, del_ptr);
112
+ return true ;
113
+ }
114
+ return false ;
115
+ }
91
116
};
92
117
93
118
template <typename T, typename std::enable_if<std::is_destructible<T>::value, int >::type = 0 >
@@ -340,7 +365,25 @@ struct smart_holder {
340
365
ensure_compatible_rtti_uqp_del<T, D>(context);
341
366
ensure_use_count_1 (context);
342
367
T *raw_ptr = as_raw_ptr_unowned<T>();
368
+
369
+ // extract the custom deleter from the holder;
370
+ D extracted_deleter;
371
+
372
+ auto *gd = std::get_deleter<guarded_delete>(vptr);
373
+
374
+ // There's no way to remove the deleter from a shared pointer, reach in and extract the
375
+ // deletion action before the shared pointer destructor invokes it.
376
+ bool found_deleter = false ;
377
+ if (gd) {
378
+ found_deleter = gd->extract_deleter <T, D>(extracted_deleter);
379
+ }
380
+
343
381
release_ownership ();
382
+
383
+ if (found_deleter) {
384
+ return std::unique_ptr<T, D>(raw_ptr, std::move (extracted_deleter));
385
+ }
386
+ // No special destructor.
344
387
return std::unique_ptr<T, D>(raw_ptr);
345
388
}
346
389
0 commit comments