Split out (almost) pure refactoring from https://github.com/pybind/pybind11/pull/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
                    + ").");
            }
```
This commit is contained in:
Ralf W. Grosse-Kunstleve 2024-08-25 22:56:22 +07:00 committed by GitHub
parent bf54ecdf9c
commit 0e49463169
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 16 deletions

View File

@ -231,6 +231,22 @@ struct smart_holder {
vptr_del_ptr->armed_flag = armed_flag;
}
// Caller is responsible for precondition: ensure_compatible_rtti_uqp_del<T, D>() must succeed.
template <typename T, typename D>
std::unique_ptr<D> extract_deleter(const char *context) const {
auto *gd = std::get_deleter<guarded_delete>(vptr);
if (gd && gd->use_del_fun) {
const auto &custom_deleter_ptr = gd->del_fun.template target<custom_deleter<T, D>>();
if (custom_deleter_ptr == nullptr) {
throw std::runtime_error(
std::string("smart_holder::extract_deleter() precondition failure (") + context
+ ").");
}
return std::unique_ptr<D>(new D(std::move(custom_deleter_ptr->deleter)));
}
return nullptr;
}
static smart_holder from_raw_ptr_unowned(void *raw_ptr) {
smart_holder hld;
hld.vptr.reset(raw_ptr, [](void *) {});

View File

@ -794,22 +794,7 @@ struct load_helper : value_and_holder_helper {
"instance cannot safely be transferred to C++.");
}
// Temporary variable to store the extracted deleter in.
std::unique_ptr<D> extracted_deleter;
auto *gd = std::get_deleter<pybindit::memory::guarded_delete>(holder().vptr);
if (gd && gd->use_del_fun) { // Note the ensure_compatible_rtti_uqp_del<T, D>() call above.
// In struct_smart_holder, a custom deleter is always stored in a guarded delete.
// The guarded delete's std::function<void(void*)> actually points at the
// custom_deleter type, so we can verify it is of the custom deleter type and
// finally extract its deleter.
using custom_deleter_D = pybindit::memory::custom_deleter<T, D>;
const auto &custom_deleter_ptr = gd->del_fun.template target<custom_deleter_D>();
assert(custom_deleter_ptr != nullptr);
// Now that we have confirmed the type of the deleter matches the desired return
// value we can extract the function.
extracted_deleter = std::unique_ptr<D>(new D(std::move(custom_deleter_ptr->deleter)));
}
std::unique_ptr<D> extracted_deleter = holder().template extract_deleter<T, D>(context);
// Critical transfer-of-ownership section. This must stay together.
if (self_life_support != nullptr) {