Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/pybind11/detail/type_caster_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -1107,11 +1107,11 @@ class type_caster_base : public type_caster_generic {
|| policy == return_value_policy::automatic_reference) {
policy = return_value_policy::copy;
}
return cast(&src, policy, parent);
return cast(std::addressof(src), policy, parent);
}

static handle cast(itype &&src, return_value_policy, handle parent) {
return cast(&src, return_value_policy::move, parent);
return cast(std::addressof(src), return_value_policy::move, parent);
}

// Returns a (pointer, type_info) pair taking care of necessary type lookup for a
Expand Down
13 changes: 13 additions & 0 deletions tests/pybind11_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <pybind11/eval.h>
#include <pybind11/pybind11.h>

#include <memory>

namespace py = pybind11;
using namespace pybind11::literals;

Expand Down Expand Up @@ -52,6 +54,17 @@ union IntFloat {
float f;
};

class UnusualOpRef {
public:
using NonTrivialType = std::shared_ptr<int>; // Almost any non-trivial type will do.
// Overriding operator& should not break pybind11.
NonTrivialType operator&() { return non_trivial_member; }
NonTrivialType operator&() const { return non_trivial_member; }

private:
NonTrivialType non_trivial_member;
};

/// Custom cast-only type that casts to a string "rvalue" or "lvalue" depending on the cast
/// context. Used to test recursive casters (e.g. std::tuple, stl containers).
struct RValueCaster {};
Expand Down
12 changes: 12 additions & 0 deletions tests/test_copy_move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ struct type_caster<CopyOnlyInt> {
PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(pybind11)

namespace {

py::object CastUnusualOpRefConstRef(const UnusualOpRef &cref) { return py::cast(cref); }
py::object CastUnusualOpRefMovable(UnusualOpRef &&mvbl) { return py::cast(std::move(mvbl)); }

} // namespace

TEST_SUBMODULE(copy_move_policies, m) {
// test_lacking_copy_ctor
py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor")
Expand Down Expand Up @@ -293,6 +300,11 @@ TEST_SUBMODULE(copy_move_policies, m) {

// Make sure that cast from pytype rvalue to other pytype works
m.def("get_pytype_rvalue_castissue", [](double i) { return py::float_(i).cast<py::int_>(); });

py::class_<UnusualOpRef>(m, "UnusualOpRef");
m.def("CallCastUnusualOpRefConstRef",
[]() { return CastUnusualOpRefConstRef(UnusualOpRef()); });
m.def("CallCastUnusualOpRefMovable", []() { return CastUnusualOpRefMovable(UnusualOpRef()); });
}

/*
Expand Down
6 changes: 6 additions & 0 deletions tests/test_copy_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,9 @@ def test_pytype_rvalue_cast():

value = m.get_pytype_rvalue_castissue(1.0)
assert value == 1


def test_unusual_op_ref():
# Merely to test that this still exists and built successfully.
assert m.CallCastUnusualOpRefConstRef().__class__.__name__ == "UnusualOpRef"
assert m.CallCastUnusualOpRefMovable().__class__.__name__ == "UnusualOpRef"