diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h index f6234c3d2..fd8c81b9a 100644 --- a/include/pybind11/detail/type_caster_base.h +++ b/include/pybind11/detail/type_caster_base.h @@ -1107,11 +1107,11 @@ public: || 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 diff --git a/tests/pybind11_tests.h b/tests/pybind11_tests.h index a7c00c2f9..7be58feb6 100644 --- a/tests/pybind11_tests.h +++ b/tests/pybind11_tests.h @@ -3,6 +3,8 @@ #include #include +#include + namespace py = pybind11; using namespace pybind11::literals; @@ -52,6 +54,17 @@ union IntFloat { float f; }; +class UnusualOpRef { +public: + using NonTrivialType = std::shared_ptr; // 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 {}; diff --git a/tests/test_copy_move.cpp b/tests/test_copy_move.cpp index 4f93defe1..ddffbe3a9 100644 --- a/tests/test_copy_move.cpp +++ b/tests/test_copy_move.cpp @@ -157,6 +157,13 @@ public: 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_(m, "lacking_copy_ctor") @@ -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::class_(m, "UnusualOpRef"); + m.def("CallCastUnusualOpRefConstRef", + []() { return CastUnusualOpRefConstRef(UnusualOpRef()); }); + m.def("CallCastUnusualOpRefMovable", []() { return CastUnusualOpRefMovable(UnusualOpRef()); }); } /* diff --git a/tests/test_copy_move.py b/tests/test_copy_move.py index 405e00132..ee046305f 100644 --- a/tests/test_copy_move.py +++ b/tests/test_copy_move.py @@ -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"