From d54d6d8c613914a7063897d5ddddc62348ffe74a Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Wed, 1 Jul 2020 01:53:09 +0200 Subject: [PATCH] Adding pybind11::cast overload for rvalue references (#1260) * Adding pybind11::cast overload for rvalue references --- include/pybind11/cast.h | 11 +++++++---- tests/test_smart_ptr.cpp | 3 ++- tests/test_smart_ptr.py | 3 +++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 28283da8f..9fa5e21d0 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1725,13 +1725,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 87c9be8c2..6f8f3821a 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 c6627043b..d275b3dc9 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