Skip to content

Commit d54d6d8

Browse files
Adding pybind11::cast overload for rvalue references (#1260)
* Adding pybind11::cast overload for rvalue references
1 parent fc3a449 commit d54d6d8

File tree

3 files changed

+12
-5
lines changed

3 files changed

+12
-5
lines changed

include/pybind11/cast.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,13 +1725,16 @@ T cast(const handle &handle) { return T(reinterpret_borrow<object>(handle)); }
17251725

17261726
// C++ type -> py::object
17271727
template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0>
1728-
object cast(const T &value, return_value_policy policy = return_value_policy::automatic_reference,
1728+
object cast(T &&value, return_value_policy policy = return_value_policy::automatic_reference,
17291729
handle parent = handle()) {
1730+
using no_ref_T = typename std::remove_reference<T>::type;
17301731
if (policy == return_value_policy::automatic)
1731-
policy = std::is_pointer<T>::value ? return_value_policy::take_ownership : return_value_policy::copy;
1732+
policy = std::is_pointer<no_ref_T>::value ? return_value_policy::take_ownership :
1733+
std::is_lvalue_reference<T>::value ? return_value_policy::copy : return_value_policy::move;
17321734
else if (policy == return_value_policy::automatic_reference)
1733-
policy = std::is_pointer<T>::value ? return_value_policy::reference : return_value_policy::copy;
1734-
return reinterpret_steal<object>(detail::make_caster<T>::cast(value, policy, parent));
1735+
policy = std::is_pointer<no_ref_T>::value ? return_value_policy::reference :
1736+
std::is_lvalue_reference<T>::value ? return_value_policy::copy : return_value_policy::move;
1737+
return reinterpret_steal<object>(detail::make_caster<T>::cast(std::forward<T>(value), policy, parent));
17351738
}
17361739

17371740
template <typename T> T handle::cast() const { return pybind11::cast<T>(*this); }

tests/test_smart_ptr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ TEST_SUBMODULE(smart_ptr, m) {
291291
~C() { print_destroyed(this); }
292292
};
293293
py::class_<C, custom_unique_ptr<C>>(m, "TypeWithMoveOnlyHolder")
294-
.def_static("make", []() { return custom_unique_ptr<C>(new C); });
294+
.def_static("make", []() { return custom_unique_ptr<C>(new C); })
295+
.def_static("make_as_object", []() { return py::cast(custom_unique_ptr<C>(new C)); });
295296

296297
// test_holder_with_addressof_operator
297298
struct TypeForHolderWithAddressOf {

tests/test_smart_ptr.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,10 @@ def test_shared_ptr_from_this_and_references():
218218

219219
def test_move_only_holder():
220220
a = m.TypeWithMoveOnlyHolder.make()
221+
b = m.TypeWithMoveOnlyHolder.make_as_object()
221222
stats = ConstructorStats.get(m.TypeWithMoveOnlyHolder)
223+
assert stats.alive() == 2
224+
del b
222225
assert stats.alive() == 1
223226
del a
224227
assert stats.alive() == 0

0 commit comments

Comments
 (0)