From c0cfe95b1b6b5db3077d6e4293686277238b4a31 Mon Sep 17 00:00:00 2001 From: Xiaofei Wang <6218006+wangxf123456@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:21:28 -0700 Subject: [PATCH] Support loading `unique_ptr` as `unique_ptr`. (#4031) * Support loading unique_ptr as unique_ptr. * Fix incorrect test * pre commit fix * Fix clang tidy * Resolve comments * Resolve comments --- include/pybind11/detail/smart_holder_poc.h | 4 +++- tests/pure_cpp/smart_holder_poc_test.cpp | 28 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/include/pybind11/detail/smart_holder_poc.h b/include/pybind11/detail/smart_holder_poc.h index 9794b1b38..de92f4156 100644 --- a/include/pybind11/detail/smart_holder_poc.h +++ b/include/pybind11/detail/smart_holder_poc.h @@ -181,7 +181,9 @@ struct smart_holder { + ")."); } ensure_vptr_is_using_builtin_delete(context); - } else if (!(*rtti_requested == *rtti_uqp_del)) { + } else if (!(*rtti_requested == *rtti_uqp_del) + && !(vptr_is_using_builtin_delete + && is_std_default_delete(*rtti_requested))) { throw std::invalid_argument(std::string("Incompatible unique_ptr deleter (") + context + ")."); } diff --git a/tests/pure_cpp/smart_holder_poc_test.cpp b/tests/pure_cpp/smart_holder_poc_test.cpp index cbdbc25f2..8a625a5c1 100644 --- a/tests/pure_cpp/smart_holder_poc_test.cpp +++ b/tests/pure_cpp/smart_holder_poc_test.cpp @@ -37,6 +37,15 @@ private: ~indestructible_int() = default; }; +struct base { + virtual int get() { return 10; } + virtual ~base() = default; +}; + +struct derived : public base { + int get() override { return 100; } +}; + } // namespace helpers TEST_CASE("from_raw_ptr_unowned+as_raw_ptr_unowned", "[S]") { @@ -227,6 +236,25 @@ TEST_CASE("from_unique_ptr+as_shared_ptr", "[S]") { REQUIRE(*new_owner == 19); } +TEST_CASE("from_unique_ptr_derived+as_unique_ptr_base", "[S]") { + std::unique_ptr orig_owner(new helpers::derived()); + auto hld = smart_holder::from_unique_ptr(std::move(orig_owner)); + REQUIRE(orig_owner.get() == nullptr); + std::unique_ptr new_owner = hld.as_unique_ptr(); + REQUIRE(!hld.has_pointee()); + REQUIRE(new_owner->get() == 100); +} + +TEST_CASE("from_unique_ptr_derived+as_unique_ptr_base2", "[E]") { + std::unique_ptr> orig_owner( + new helpers::derived()); + auto hld = smart_holder::from_unique_ptr(std::move(orig_owner)); + REQUIRE(orig_owner.get() == nullptr); + REQUIRE_THROWS_WITH( + (hld.as_unique_ptr>()), + "Incompatible unique_ptr deleter (as_unique_ptr)."); +} + TEST_CASE("from_unique_ptr_with_deleter+as_lvalue_ref", "[S]") { std::unique_ptr> orig_owner(new int(19)); auto hld = smart_holder::from_unique_ptr(std::move(orig_owner));