File tree Expand file tree Collapse file tree 3 files changed +49
-0
lines changed Expand file tree Collapse file tree 3 files changed +49
-0
lines changed Original file line number Diff line number Diff line change @@ -1630,6 +1630,22 @@ struct move_only_holder_caster : type_caster_base<type> {
1630
1630
using base::typeinfo;
1631
1631
using base::value;
1632
1632
1633
+ // We must explicitly define the default constructor(s) since we define a
1634
+ // destructor; otherwise, the compiler will incorrectly use the copy
1635
+ // constructor.
1636
+ move_only_holder_caster () = default ;
1637
+ move_only_holder_caster (move_only_holder_caster&&) = default ;
1638
+ move_only_holder_caster (const move_only_holder_caster&) = delete ;
1639
+ ~move_only_holder_caster () {
1640
+ if (holder) {
1641
+ // If the argument was loaded into C++, but not transferred out,
1642
+ // then this was most likely part of a failed overload in
1643
+ // `argument_loader`. Transfer ownership back to Python.
1644
+ move_only_holder_caster::cast (
1645
+ std::move (holder), return_value_policy{}, handle{});
1646
+ }
1647
+ }
1648
+
1633
1649
static_assert (std::is_base_of<type_caster_base<type>, type_caster<type>>::value,
1634
1650
" Holder classes are only supported for custom types" );
1635
1651
Original file line number Diff line number Diff line change @@ -335,6 +335,28 @@ TEST_SUBMODULE(smart_ptr, m) {
335
335
return py::cast (std::move (obj));
336
336
});
337
337
338
+ class FirstT {};
339
+ py::class_<FirstT>(m, " FirstT" )
340
+ .def (py::init ());
341
+ class SecondT {};
342
+ py::class_<SecondT>(m, " SecondT" )
343
+ .def (py::init ());
344
+
345
+ m.def (" unique_ptr_overload" ,
346
+ [](std::unique_ptr<UniquePtrHeld> obj, FirstT) {
347
+ py::dict out;
348
+ out[" obj" ] = py::cast (std::move (obj));
349
+ out[" overload" ] = 1 ;
350
+ return out;
351
+ });
352
+ m.def (" unique_ptr_overload" ,
353
+ [](std::unique_ptr<UniquePtrHeld> obj, SecondT) {
354
+ py::dict out;
355
+ out[" obj" ] = py::cast (std::move (obj));
356
+ out[" overload" ] = 2 ;
357
+ return out;
358
+ });
359
+
338
360
// Ensure class is non-empty, so it's easier to detect double-free
339
361
// corruption. (If empty, this may be harder to see easily.)
340
362
struct SharedPtrHeld { int value = 10 ; };
Original file line number Diff line number Diff line change @@ -258,3 +258,14 @@ def test_unique_ptr_arg():
258
258
def test_unique_ptr_to_shared_ptr ():
259
259
obj = m .shared_ptr_held_in_unique_ptr ()
260
260
assert m .shared_ptr_held_func (obj )
261
+
262
+
263
+ def test_unique_ptr_overload_fail ():
264
+ obj = m .UniquePtrHeld (1 )
265
+ # These overloads pass ownership back to Python.
266
+ out = m .unique_ptr_overload (obj , m .FirstT ())
267
+ assert out ["obj" ] is obj
268
+ assert out ["overload" ] == 1
269
+ out = m .unique_ptr_overload (obj , m .SecondT ())
270
+ assert out ["obj" ] is obj
271
+ assert out ["overload" ] == 2
You can’t perform that action at this time.
0 commit comments