Skip to content

Commit c0cfe95

Browse files
authored
Support loading unique_ptr<Derived> as unique_ptr<Base>. (#4031)
* Support loading unique_ptr<derived> as unique_ptr<base>. * Fix incorrect test * pre commit fix * Fix clang tidy * Resolve comments * Resolve comments
1 parent cf2c307 commit c0cfe95

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

include/pybind11/detail/smart_holder_poc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ struct smart_holder {
181181
+ ").");
182182
}
183183
ensure_vptr_is_using_builtin_delete(context);
184-
} else if (!(*rtti_requested == *rtti_uqp_del)) {
184+
} else if (!(*rtti_requested == *rtti_uqp_del)
185+
&& !(vptr_is_using_builtin_delete
186+
&& is_std_default_delete<T>(*rtti_requested))) {
185187
throw std::invalid_argument(std::string("Incompatible unique_ptr deleter (") + context
186188
+ ").");
187189
}

tests/pure_cpp/smart_holder_poc_test.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ struct indestructible_int {
3737
~indestructible_int() = default;
3838
};
3939

40+
struct base {
41+
virtual int get() { return 10; }
42+
virtual ~base() = default;
43+
};
44+
45+
struct derived : public base {
46+
int get() override { return 100; }
47+
};
48+
4049
} // namespace helpers
4150

4251
TEST_CASE("from_raw_ptr_unowned+as_raw_ptr_unowned", "[S]") {
@@ -227,6 +236,25 @@ TEST_CASE("from_unique_ptr+as_shared_ptr", "[S]") {
227236
REQUIRE(*new_owner == 19);
228237
}
229238

239+
TEST_CASE("from_unique_ptr_derived+as_unique_ptr_base", "[S]") {
240+
std::unique_ptr<helpers::derived> orig_owner(new helpers::derived());
241+
auto hld = smart_holder::from_unique_ptr(std::move(orig_owner));
242+
REQUIRE(orig_owner.get() == nullptr);
243+
std::unique_ptr<helpers::base> new_owner = hld.as_unique_ptr<helpers::base>();
244+
REQUIRE(!hld.has_pointee());
245+
REQUIRE(new_owner->get() == 100);
246+
}
247+
248+
TEST_CASE("from_unique_ptr_derived+as_unique_ptr_base2", "[E]") {
249+
std::unique_ptr<helpers::derived, helpers::functor_other_delete<helpers::derived>> orig_owner(
250+
new helpers::derived());
251+
auto hld = smart_holder::from_unique_ptr(std::move(orig_owner));
252+
REQUIRE(orig_owner.get() == nullptr);
253+
REQUIRE_THROWS_WITH(
254+
(hld.as_unique_ptr<helpers::base, helpers::functor_builtin_delete<helpers::base>>()),
255+
"Incompatible unique_ptr deleter (as_unique_ptr).");
256+
}
257+
230258
TEST_CASE("from_unique_ptr_with_deleter+as_lvalue_ref", "[S]") {
231259
std::unique_ptr<int, helpers::functor_builtin_delete<int>> orig_owner(new int(19));
232260
auto hld = smart_holder::from_unique_ptr(std::move(orig_owner));

0 commit comments

Comments
 (0)