Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[smart_holder] Split out (almost) pure refactoring from PR #5332 #5334

Merged

Conversation

rwgk
Copy link
Collaborator

@rwgk rwgk commented Aug 25, 2024

Description

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
                    + ").");
            }

@rhaschke FYI

@iwanders FYI (related: #4850, #4921, #4924)

Suggested changelog entry:

PREPARATION for:

PR pybind#5332 — Fix handling of const unique_ptr<T, D> & (do not disown).

Splitting out so that the functional changes under PR pybind#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
                    + ").");
            }
```
@rwgk rwgk marked this pull request as ready for review August 25, 2024 15:55
@rwgk rwgk merged commit 0e49463 into pybind:smart_holder Aug 25, 2024
78 of 79 checks passed
@rwgk rwgk deleted the unique_ptr_cref_sh_factor_out_extract_deleter branch August 25, 2024 15:56
@github-actions github-actions bot added the needs changelog Possibly needs a changelog entry label Aug 25, 2024
@rwgk rwgk removed the needs changelog Possibly needs a changelog entry label Aug 25, 2024
// 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this can be const?

Suggested change
auto *gd = std::get_deleter<guarded_delete>(vptr);
const auto *gd = std::get_deleter<guarded_delete>(vptr);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks!

Applied here:

a0be89d

There is actually another detail here that I'm unsure about, a little further down:

            return std::unique_ptr<D>(new D(std::move(custom_deleter_ptr->deleter)));

Is the std::move() there what we want?

Tests pass without it. (I ran local testing only, Linux gcc.)

From looking at

it isn't clear to me if the Deleter is required to be copyable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! I think it is not required, see the constructor for unique_ptr:

Specifically the notes for the 3,4) signatures:

If D is non-reference type A, then the signatures are:
unique_ptr(pointer p, const A& d) noexcept; (1) (requires that Deleter is nothrow-CopyConstructible)
unique_ptr(pointer p, A&& d) noexcept; (2) (requires that Deleter is nothrow-MoveConstructible)

So I think moving is the correct thing to do in case the second signature was used to create the unique pointer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Now I'm backtracking to: While it's not a requirement in the ISO standard, should it be a requirement here?

Because we are extracting the deleter multiple times: each time we build a const unique_ptr<T, D> & with the code under #5332.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, well, yeah if we end up extracting the deleter multiple times... we should not be moving it, and probably want a static assert to ensure it is actually copyable?

rwgk pushed a commit to rwgk/pybind11 that referenced this pull request Aug 25, 2024
rwgk pushed a commit to rwgk/pybind11 that referenced this pull request Aug 25, 2024
rwgk pushed a commit that referenced this pull request Aug 25, 2024
…own). (#5332)

* Replace `unique_ptr_cref_roundtrip()` with `pass_unique_ptr_cref()`, `rtrn_unique_ptr_cref()` to make the current behavior obvious.

* add in unique_ptr_storage, unique_ptr_storage_deleter

* Add shared_ptr_storage (with that disowning fails as expected).

* Add load_as_const_unique_ptr()

* Restore original struct_smart_holder.h

* factor out `smart_holder::extract_deleter()`

* Better error message.

* Misc cleanup/tidying.

* Use `re.match("ctor_arg(_MvCtor)*_MvCtor", ...)` for compatibility with MSVC, NVHPC, ICC

* Add small comments.

* Fix small, inconsequential oversight in test code.

* Apply suggestion by @iwanders under PR #5334

* Remove `std::move()` in `smart_holder::extract_deleter()`

* Add `static_assert()` following a suggestion by @iwanders under PR #5334
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants