Skip to content

Commit 82d7824

Browse files
authored
Use std::addressof() in type_caster_base.h and smart_holder_type_casters.h (#30093)
* changes as transferred from CL * Add minimal tests. * Add `non_trivial_member` to make the test more realistic and avoid clang-tidy errors. * Also cover `CastConstRef` (to be verified). * `type_caster::cast(const &)` evidently does not need `std::addressof()` * Slightly simplify `UnusualOpRef` * Reorganize tests so that it is easy to backport the type_caster_base.h change plus test.
1 parent 47b666d commit 82d7824

7 files changed

+48
-2
lines changed

include/pybind11/detail/smart_holder_type_casters.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
746746

747747
static handle cast(T &&src, return_value_policy /*policy*/, handle parent) {
748748
// type_caster_base BEGIN
749-
return cast(&src, return_value_policy::move, parent);
749+
return cast(std::addressof(src), return_value_policy::move, parent);
750750
// type_caster_base END
751751
}
752752

include/pybind11/detail/type_caster_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1120,7 +1120,7 @@ class type_caster_base : public type_caster_generic {
11201120
}
11211121

11221122
static handle cast(itype &&src, return_value_policy, handle parent) {
1123-
return cast(&src, return_value_policy::move, parent);
1123+
return cast(std::addressof(src), return_value_policy::move, parent);
11241124
}
11251125

11261126
// Returns a (pointer, type_info) pair taking care of necessary type lookup for a

tests/pybind11_tests.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <pybind11/eval.h>
44
#include <pybind11/pybind11.h>
55

6+
#include <memory>
7+
68
namespace py = pybind11;
79
using namespace pybind11::literals;
810

@@ -52,6 +54,15 @@ union IntFloat {
5254
float f;
5355
};
5456

57+
class UnusualOpRef {
58+
public:
59+
using NonTrivialType = std::shared_ptr<int>; // Almost any non-trivial type will do.
60+
NonTrivialType operator&() { return non_trivial_member; } // UNUSUAL operator.
61+
62+
private:
63+
NonTrivialType non_trivial_member;
64+
};
65+
5566
/// Custom cast-only type that casts to a string "rvalue" or "lvalue" depending on the cast
5667
/// context. Used to test recursive casters (e.g. std::tuple, stl containers).
5768
struct RValueCaster {};

tests/test_class_sh_basic.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,17 @@ struct SharedPtrStash {
129129
void Add(const std::shared_ptr<const atyp> &obj) { stash.push_back(obj); }
130130
};
131131

132+
class LocalUnusualOpRef : UnusualOpRef {}; // To avoid clashing with `py::class_<UnusualOpRef>`.
133+
py::object CastUnusualOpRefConstRef(const LocalUnusualOpRef &cref) { return py::cast(cref); }
134+
py::object CastUnusualOpRefMovable(LocalUnusualOpRef &&mvbl) { return py::cast(std::move(mvbl)); }
135+
132136
} // namespace class_sh_basic
133137
} // namespace pybind11_tests
134138

135139
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_basic::atyp)
136140
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_basic::uconsumer)
137141
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_basic::SharedPtrStash)
142+
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_basic::LocalUnusualOpRef)
138143

139144
namespace pybind11_tests {
140145
namespace class_sh_basic {
@@ -227,6 +232,12 @@ TEST_SUBMODULE(class_sh_basic, m) {
227232
"rtrn_uq_automatic_reference",
228233
[]() { return std::unique_ptr<atyp>(new atyp("rtrn_uq_automatic_reference")); },
229234
pybind11::return_value_policy::automatic_reference);
235+
236+
py::classh<LocalUnusualOpRef>(m, "LocalUnusualOpRef");
237+
m.def("CallCastUnusualOpRefConstRef",
238+
[]() { return CastUnusualOpRefConstRef(LocalUnusualOpRef()); });
239+
m.def("CallCastUnusualOpRefMovable",
240+
[]() { return CastUnusualOpRefMovable(LocalUnusualOpRef()); });
230241
}
231242

232243
} // namespace class_sh_basic

tests/test_class_sh_basic.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,9 @@ def test_function_signatures(doc):
216216

217217
def test_unique_ptr_return_value_policy_automatic_reference():
218218
assert m.get_mtxt(m.rtrn_uq_automatic_reference()) == "rtrn_uq_automatic_reference"
219+
220+
221+
def test_unusual_op_ref():
222+
# Merely to test that this still exists and built successfully.
223+
assert m.CallCastUnusualOpRefConstRef().__class__.__name__ == "LocalUnusualOpRef"
224+
assert m.CallCastUnusualOpRefMovable().__class__.__name__ == "LocalUnusualOpRef"

tests/test_copy_move.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ struct type_caster<CopyOnlyInt> {
157157
PYBIND11_NAMESPACE_END(detail)
158158
PYBIND11_NAMESPACE_END(pybind11)
159159

160+
namespace {
161+
162+
py::object CastUnusualOpRefConstRef(const UnusualOpRef &cref) { return py::cast(cref); }
163+
py::object CastUnusualOpRefMovable(UnusualOpRef &&mvbl) { return py::cast(std::move(mvbl)); }
164+
165+
} // namespace
166+
160167
TEST_SUBMODULE(copy_move_policies, m) {
161168
// test_lacking_copy_ctor
162169
py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor")
@@ -295,6 +302,11 @@ TEST_SUBMODULE(copy_move_policies, m) {
295302
// Make sure that cast from pytype rvalue to other pytype works
296303
m.def("get_pytype_rvalue_castissue", [](double i) { return py::float_(i).cast<py::int_>(); });
297304

305+
py::class_<UnusualOpRef>(m, "UnusualOpRef");
306+
m.def("CallCastUnusualOpRefConstRef",
307+
[]() { return CastUnusualOpRefConstRef(UnusualOpRef()); });
308+
m.def("CallCastUnusualOpRefMovable", []() { return CastUnusualOpRefMovable(UnusualOpRef()); });
309+
298310
// Mimic situation generated by PyCLIF-pybind11.
299311
// Requires `case return_value_policy::_clif_automatic` in `type_caster_base`.
300312
struct PyCastUsingClifAutomaticTestType {};

tests/test_copy_move.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ def test_pytype_rvalue_cast():
132132
assert value == 1
133133

134134

135+
def test_unusual_op_ref():
136+
# Merely to test that this still exists and built successfully.
137+
assert m.CallCastUnusualOpRefConstRef().__class__.__name__ == "UnusualOpRef"
138+
assert m.CallCastUnusualOpRefMovable().__class__.__name__ == "UnusualOpRef"
139+
140+
135141
def test_py_cast_using_clif_automatic():
136142
obj = m.py_cast_using_clif_automatic()
137143
assert obj.__class__.__name__ == "PyCastUsingClifAutomaticTestType"

0 commit comments

Comments
 (0)