github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/pybind11/tests/test_copy_move.cpp (about) 1 /* 2 tests/test_copy_move_policies.cpp -- 'copy' and 'move' return value policies 3 and related tests 4 5 Copyright (c) 2016 Ben North <ben@redfrontdoor.org> 6 7 All rights reserved. Use of this source code is governed by a 8 BSD-style license that can be found in the LICENSE file. 9 */ 10 11 #include <pybind11/stl.h> 12 13 #include "constructor_stats.h" 14 #include "pybind11_tests.h" 15 16 template <typename derived> 17 struct empty { 18 static const derived &get_one() { return instance_; } 19 static derived instance_; 20 }; 21 22 struct lacking_copy_ctor : public empty<lacking_copy_ctor> { 23 lacking_copy_ctor() = default; 24 lacking_copy_ctor(const lacking_copy_ctor &other) = delete; 25 }; 26 27 template <> 28 lacking_copy_ctor empty<lacking_copy_ctor>::instance_ = {}; 29 30 struct lacking_move_ctor : public empty<lacking_move_ctor> { 31 lacking_move_ctor() = default; 32 lacking_move_ctor(const lacking_move_ctor &other) = delete; 33 lacking_move_ctor(lacking_move_ctor &&other) = delete; 34 }; 35 36 template <> 37 lacking_move_ctor empty<lacking_move_ctor>::instance_ = {}; 38 39 /* Custom type caster move/copy test classes */ 40 class MoveOnlyInt { 41 public: 42 MoveOnlyInt() { print_default_created(this); } 43 explicit MoveOnlyInt(int v) : value{v} { print_created(this, value); } 44 MoveOnlyInt(MoveOnlyInt &&m) noexcept { 45 print_move_created(this, m.value); 46 std::swap(value, m.value); 47 } 48 MoveOnlyInt &operator=(MoveOnlyInt &&m) noexcept { 49 print_move_assigned(this, m.value); 50 std::swap(value, m.value); 51 return *this; 52 } 53 MoveOnlyInt(const MoveOnlyInt &) = delete; 54 MoveOnlyInt &operator=(const MoveOnlyInt &) = delete; 55 ~MoveOnlyInt() { print_destroyed(this); } 56 57 int value; 58 }; 59 class MoveOrCopyInt { 60 public: 61 MoveOrCopyInt() { print_default_created(this); } 62 explicit MoveOrCopyInt(int v) : value{v} { print_created(this, value); } 63 MoveOrCopyInt(MoveOrCopyInt &&m) noexcept { 64 print_move_created(this, m.value); 65 std::swap(value, m.value); 66 } 67 MoveOrCopyInt &operator=(MoveOrCopyInt &&m) noexcept { 68 print_move_assigned(this, m.value); 69 std::swap(value, m.value); 70 return *this; 71 } 72 MoveOrCopyInt(const MoveOrCopyInt &c) { 73 print_copy_created(this, c.value); 74 // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) 75 value = c.value; 76 } 77 MoveOrCopyInt &operator=(const MoveOrCopyInt &c) { 78 print_copy_assigned(this, c.value); 79 value = c.value; 80 return *this; 81 } 82 ~MoveOrCopyInt() { print_destroyed(this); } 83 84 int value; 85 }; 86 class CopyOnlyInt { 87 public: 88 CopyOnlyInt() { print_default_created(this); } 89 explicit CopyOnlyInt(int v) : value{v} { print_created(this, value); } 90 CopyOnlyInt(const CopyOnlyInt &c) { 91 print_copy_created(this, c.value); 92 // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) 93 value = c.value; 94 } 95 CopyOnlyInt &operator=(const CopyOnlyInt &c) { 96 print_copy_assigned(this, c.value); 97 value = c.value; 98 return *this; 99 } 100 ~CopyOnlyInt() { print_destroyed(this); } 101 102 int value; 103 }; 104 PYBIND11_NAMESPACE_BEGIN(pybind11) 105 PYBIND11_NAMESPACE_BEGIN(detail) 106 template <> 107 struct type_caster<MoveOnlyInt> { 108 PYBIND11_TYPE_CASTER(MoveOnlyInt, const_name("MoveOnlyInt")); 109 bool load(handle src, bool) { 110 value = MoveOnlyInt(src.cast<int>()); 111 return true; 112 } 113 static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) { 114 return pybind11::cast(m.value, r, p); 115 } 116 }; 117 118 template <> 119 struct type_caster<MoveOrCopyInt> { 120 PYBIND11_TYPE_CASTER(MoveOrCopyInt, const_name("MoveOrCopyInt")); 121 bool load(handle src, bool) { 122 value = MoveOrCopyInt(src.cast<int>()); 123 return true; 124 } 125 static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) { 126 return pybind11::cast(m.value, r, p); 127 } 128 }; 129 130 template <> 131 struct type_caster<CopyOnlyInt> { 132 protected: 133 CopyOnlyInt value; 134 135 public: 136 static constexpr auto name = const_name("CopyOnlyInt"); 137 bool load(handle src, bool) { 138 value = CopyOnlyInt(src.cast<int>()); 139 return true; 140 } 141 static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { 142 return pybind11::cast(m.value, r, p); 143 } 144 static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) { 145 if (!src) { 146 return none().release(); 147 } 148 return cast(*src, policy, parent); 149 } 150 explicit operator CopyOnlyInt *() { return &value; } 151 explicit operator CopyOnlyInt &() { return value; } 152 template <typename T> 153 using cast_op_type = pybind11::detail::cast_op_type<T>; 154 }; 155 PYBIND11_NAMESPACE_END(detail) 156 PYBIND11_NAMESPACE_END(pybind11) 157 158 TEST_SUBMODULE(copy_move_policies, m) { 159 // test_lacking_copy_ctor 160 py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor") 161 .def_static("get_one", &lacking_copy_ctor::get_one, py::return_value_policy::copy); 162 // test_lacking_move_ctor 163 py::class_<lacking_move_ctor>(m, "lacking_move_ctor") 164 .def_static("get_one", &lacking_move_ctor::get_one, py::return_value_policy::move); 165 166 // test_move_and_copy_casts 167 // NOLINTNEXTLINE(performance-unnecessary-value-param) 168 m.def("move_and_copy_casts", [](const py::object &o) { 169 int r = 0; 170 r += py::cast<MoveOrCopyInt>(o).value; /* moves */ 171 r += py::cast<MoveOnlyInt>(o).value; /* moves */ 172 r += py::cast<CopyOnlyInt>(o).value; /* copies */ 173 auto m1(py::cast<MoveOrCopyInt>(o)); /* moves */ 174 auto m2(py::cast<MoveOnlyInt>(o)); /* moves */ 175 auto m3(py::cast<CopyOnlyInt>(o)); /* copies */ 176 r += m1.value + m2.value + m3.value; 177 178 return r; 179 }); 180 181 // test_move_and_copy_loads 182 m.def("move_only", [](MoveOnlyInt m) { return m.value; }); 183 // Changing this breaks the existing test: needs careful review. 184 // NOLINTNEXTLINE(performance-unnecessary-value-param) 185 m.def("move_or_copy", [](MoveOrCopyInt m) { return m.value; }); 186 // Changing this breaks the existing test: needs careful review. 187 // NOLINTNEXTLINE(performance-unnecessary-value-param) 188 m.def("copy_only", [](CopyOnlyInt m) { return m.value; }); 189 m.def("move_pair", 190 [](std::pair<MoveOnlyInt, MoveOrCopyInt> p) { return p.first.value + p.second.value; }); 191 m.def("move_tuple", [](std::tuple<MoveOnlyInt, MoveOrCopyInt, MoveOnlyInt> t) { 192 return std::get<0>(t).value + std::get<1>(t).value + std::get<2>(t).value; 193 }); 194 m.def("copy_tuple", [](std::tuple<CopyOnlyInt, CopyOnlyInt> t) { 195 return std::get<0>(t).value + std::get<1>(t).value; 196 }); 197 m.def("move_copy_nested", 198 [](std::pair<MoveOnlyInt, 199 std::pair<std::tuple<MoveOrCopyInt, CopyOnlyInt, std::tuple<MoveOnlyInt>>, 200 MoveOrCopyInt>> x) { 201 return x.first.value + std::get<0>(x.second.first).value 202 + std::get<1>(x.second.first).value 203 + std::get<0>(std::get<2>(x.second.first)).value + x.second.second.value; 204 }); 205 m.def("move_and_copy_cstats", []() { 206 ConstructorStats::gc(); 207 // Reset counts to 0 so that previous tests don't affect later ones: 208 auto &mc = ConstructorStats::get<MoveOrCopyInt>(); 209 mc.move_assignments = mc.move_constructions = mc.copy_assignments = mc.copy_constructions 210 = 0; 211 auto &mo = ConstructorStats::get<MoveOnlyInt>(); 212 mo.move_assignments = mo.move_constructions = mo.copy_assignments = mo.copy_constructions 213 = 0; 214 auto &co = ConstructorStats::get<CopyOnlyInt>(); 215 co.move_assignments = co.move_constructions = co.copy_assignments = co.copy_constructions 216 = 0; 217 py::dict d; 218 d["MoveOrCopyInt"] = py::cast(mc, py::return_value_policy::reference); 219 d["MoveOnlyInt"] = py::cast(mo, py::return_value_policy::reference); 220 d["CopyOnlyInt"] = py::cast(co, py::return_value_policy::reference); 221 return d; 222 }); 223 #ifdef PYBIND11_HAS_OPTIONAL 224 // test_move_and_copy_load_optional 225 m.attr("has_optional") = true; 226 m.def("move_optional", [](std::optional<MoveOnlyInt> o) { return o->value; }); 227 m.def("move_or_copy_optional", [](std::optional<MoveOrCopyInt> o) { return o->value; }); 228 m.def("copy_optional", [](std::optional<CopyOnlyInt> o) { return o->value; }); 229 m.def("move_optional_tuple", 230 [](std::optional<std::tuple<MoveOrCopyInt, MoveOnlyInt, CopyOnlyInt>> x) { 231 return std::get<0>(*x).value + std::get<1>(*x).value + std::get<2>(*x).value; 232 }); 233 #else 234 m.attr("has_optional") = false; 235 #endif 236 237 // #70 compilation issue if operator new is not public - simple body added 238 // but not needed on most compilers; MSVC and nvcc don't like a local 239 // struct not having a method defined when declared, since it can not be 240 // added later. 241 struct PrivateOpNew { 242 int value = 1; 243 244 private: 245 void *operator new(size_t bytes) { 246 void *ptr = std::malloc(bytes); 247 if (ptr) { 248 return ptr; 249 } 250 throw std::bad_alloc{}; 251 } 252 }; 253 py::class_<PrivateOpNew>(m, "PrivateOpNew").def_readonly("value", &PrivateOpNew::value); 254 m.def("private_op_new_value", []() { return PrivateOpNew(); }); 255 m.def( 256 "private_op_new_reference", 257 []() -> const PrivateOpNew & { 258 static PrivateOpNew x{}; 259 return x; 260 }, 261 py::return_value_policy::reference); 262 263 // test_move_fallback 264 // #389: rvp::move should fall-through to copy on non-movable objects 265 struct MoveIssue1 { 266 int v; 267 explicit MoveIssue1(int v) : v{v} {} 268 MoveIssue1(const MoveIssue1 &c) = default; 269 MoveIssue1(MoveIssue1 &&) = delete; 270 }; 271 py::class_<MoveIssue1>(m, "MoveIssue1") 272 .def(py::init<int>()) 273 .def_readwrite("value", &MoveIssue1::v); 274 275 struct MoveIssue2 { 276 int v; 277 explicit MoveIssue2(int v) : v{v} {} 278 MoveIssue2(MoveIssue2 &&) = default; 279 }; 280 py::class_<MoveIssue2>(m, "MoveIssue2") 281 .def(py::init<int>()) 282 .def_readwrite("value", &MoveIssue2::v); 283 284 // #2742: Don't expect ownership of raw pointer to `new`ed object to be transferred with 285 // `py::return_value_policy::move` 286 m.def( 287 "get_moveissue1", 288 [](int i) { return std::unique_ptr<MoveIssue1>(new MoveIssue1(i)); }, 289 py::return_value_policy::move); 290 m.def( 291 "get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move); 292 293 // Make sure that cast from pytype rvalue to other pytype works 294 m.def("get_pytype_rvalue_castissue", [](double i) { return py::float_(i).cast<py::int_>(); }); 295 }