Skip to content

Commit 0e49463

Browse files
authored
Split out (almost) pure refactoring from #5332 (#5334)
PREPARATION for: PR #5332 — Fix handling of const unique_ptr<T, D> & (do not disown). Splitting out so that the functional changes under PR #5332 will be more obvious. The only functional change under this PR is that ``` assert(custom_deleter_ptr != nullptr); ``` is replaced with: ``` if (custom_deleter_ptr == nullptr) { throw std::runtime_error( std::string("smart_holder::extract_deleter() precondition failure (") + context + ")."); } ```
1 parent bf54ecd commit 0e49463

File tree

2 files changed

+17
-16
lines changed

2 files changed

+17
-16
lines changed

include/pybind11/detail/struct_smart_holder.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,22 @@ struct smart_holder {
231231
vptr_del_ptr->armed_flag = armed_flag;
232232
}
233233

234+
// Caller is responsible for precondition: ensure_compatible_rtti_uqp_del<T, D>() must succeed.
235+
template <typename T, typename D>
236+
std::unique_ptr<D> extract_deleter(const char *context) const {
237+
auto *gd = std::get_deleter<guarded_delete>(vptr);
238+
if (gd && gd->use_del_fun) {
239+
const auto &custom_deleter_ptr = gd->del_fun.template target<custom_deleter<T, D>>();
240+
if (custom_deleter_ptr == nullptr) {
241+
throw std::runtime_error(
242+
std::string("smart_holder::extract_deleter() precondition failure (") + context
243+
+ ").");
244+
}
245+
return std::unique_ptr<D>(new D(std::move(custom_deleter_ptr->deleter)));
246+
}
247+
return nullptr;
248+
}
249+
234250
static smart_holder from_raw_ptr_unowned(void *raw_ptr) {
235251
smart_holder hld;
236252
hld.vptr.reset(raw_ptr, [](void *) {});

include/pybind11/detail/type_caster_base.h

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -794,22 +794,7 @@ struct load_helper : value_and_holder_helper {
794794
"instance cannot safely be transferred to C++.");
795795
}
796796

797-
// Temporary variable to store the extracted deleter in.
798-
std::unique_ptr<D> extracted_deleter;
799-
800-
auto *gd = std::get_deleter<pybindit::memory::guarded_delete>(holder().vptr);
801-
if (gd && gd->use_del_fun) { // Note the ensure_compatible_rtti_uqp_del<T, D>() call above.
802-
// In struct_smart_holder, a custom deleter is always stored in a guarded delete.
803-
// The guarded delete's std::function<void(void*)> actually points at the
804-
// custom_deleter type, so we can verify it is of the custom deleter type and
805-
// finally extract its deleter.
806-
using custom_deleter_D = pybindit::memory::custom_deleter<T, D>;
807-
const auto &custom_deleter_ptr = gd->del_fun.template target<custom_deleter_D>();
808-
assert(custom_deleter_ptr != nullptr);
809-
// Now that we have confirmed the type of the deleter matches the desired return
810-
// value we can extract the function.
811-
extracted_deleter = std::unique_ptr<D>(new D(std::move(custom_deleter_ptr->deleter)));
812-
}
797+
std::unique_ptr<D> extracted_deleter = holder().template extract_deleter<T, D>(context);
813798

814799
// Critical transfer-of-ownership section. This must stay together.
815800
if (self_life_support != nullptr) {

0 commit comments

Comments
 (0)