diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 80abb2b93a..afd9153f1c 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1667,13 +1667,16 @@ T cast(const handle &handle) { return T(reinterpret_borrow(handle)); } // C++ type -> py::object template ::value, int> = 0> -object cast(const T &value, return_value_policy policy = return_value_policy::automatic_reference, +object cast(T &&value, return_value_policy policy = return_value_policy::automatic_reference, handle parent = handle()) { + using no_ref_T = typename std::remove_reference::type; if (policy == return_value_policy::automatic) - policy = std::is_pointer::value ? return_value_policy::take_ownership : return_value_policy::copy; + policy = std::is_pointer::value ? return_value_policy::take_ownership : + std::is_lvalue_reference::value ? return_value_policy::copy : return_value_policy::move; else if (policy == return_value_policy::automatic_reference) - policy = std::is_pointer::value ? return_value_policy::reference : return_value_policy::copy; - return reinterpret_steal(detail::make_caster::cast(value, policy, parent)); + policy = std::is_pointer::value ? return_value_policy::reference : + std::is_lvalue_reference::value ? return_value_policy::copy : return_value_policy::move; + return reinterpret_steal(detail::make_caster::cast(std::forward(value), policy, parent)); } template T handle::cast() const { return pybind11::cast(*this); } diff --git a/tests/test_smart_ptr.cpp b/tests/test_smart_ptr.cpp index 87c9be8c2b..6f8f3821a5 100644 --- a/tests/test_smart_ptr.cpp +++ b/tests/test_smart_ptr.cpp @@ -291,7 +291,8 @@ TEST_SUBMODULE(smart_ptr, m) { ~C() { print_destroyed(this); } }; py::class_>(m, "TypeWithMoveOnlyHolder") - .def_static("make", []() { return custom_unique_ptr(new C); }); + .def_static("make", []() { return custom_unique_ptr(new C); }) + .def_static("make_as_object", []() { return py::cast(custom_unique_ptr(new C)); }); // test_holder_with_addressof_operator struct TypeForHolderWithAddressOf { diff --git a/tests/test_smart_ptr.py b/tests/test_smart_ptr.py index 72b1c2a16c..63f78daef0 100644 --- a/tests/test_smart_ptr.py +++ b/tests/test_smart_ptr.py @@ -218,7 +218,10 @@ def test_shared_ptr_from_this_and_references(): def test_move_only_holder(): a = m.TypeWithMoveOnlyHolder.make() + b = m.TypeWithMoveOnlyHolder.make_as_object() stats = ConstructorStats.get(m.TypeWithMoveOnlyHolder) + assert stats.alive() == 2 + del b assert stats.alive() == 1 del a assert stats.alive() == 0