diff options
Diffstat (limited to '3rdparty/pybind11/tests/test_copy_move.cpp')
-rw-r--r-- | 3rdparty/pybind11/tests/test_copy_move.cpp | 236 |
1 files changed, 156 insertions, 80 deletions
diff --git a/3rdparty/pybind11/tests/test_copy_move.cpp b/3rdparty/pybind11/tests/test_copy_move.cpp index 2704217a..28c24456 100644 --- a/3rdparty/pybind11/tests/test_copy_move.cpp +++ b/3rdparty/pybind11/tests/test_copy_move.cpp @@ -8,38 +8,48 @@ BSD-style license that can be found in the LICENSE file. */ -#include "pybind11_tests.h" -#include "constructor_stats.h" #include <pybind11/stl.h> +#include "constructor_stats.h" +#include "pybind11_tests.h" + template <typename derived> struct empty { - static const derived& get_one() { return instance_; } + static const derived &get_one() { return instance_; } static derived instance_; }; struct lacking_copy_ctor : public empty<lacking_copy_ctor> { lacking_copy_ctor() = default; - lacking_copy_ctor(const lacking_copy_ctor& other) = delete; + lacking_copy_ctor(const lacking_copy_ctor &other) = delete; }; -template <> lacking_copy_ctor empty<lacking_copy_ctor>::instance_ = {}; +template <> +lacking_copy_ctor empty<lacking_copy_ctor>::instance_ = {}; struct lacking_move_ctor : public empty<lacking_move_ctor> { lacking_move_ctor() = default; - lacking_move_ctor(const lacking_move_ctor& other) = delete; - lacking_move_ctor(lacking_move_ctor&& other) = delete; + lacking_move_ctor(const lacking_move_ctor &other) = delete; + lacking_move_ctor(lacking_move_ctor &&other) = delete; }; -template <> lacking_move_ctor empty<lacking_move_ctor>::instance_ = {}; +template <> +lacking_move_ctor empty<lacking_move_ctor>::instance_ = {}; /* Custom type caster move/copy test classes */ class MoveOnlyInt { public: MoveOnlyInt() { print_default_created(this); } - MoveOnlyInt(int v) : value{std::move(v)} { print_created(this, value); } - MoveOnlyInt(MoveOnlyInt &&m) { print_move_created(this, m.value); std::swap(value, m.value); } - MoveOnlyInt &operator=(MoveOnlyInt &&m) { print_move_assigned(this, m.value); std::swap(value, m.value); return *this; } + explicit MoveOnlyInt(int v) : value{v} { print_created(this, value); } + MoveOnlyInt(MoveOnlyInt &&m) noexcept { + print_move_created(this, m.value); + std::swap(value, m.value); + } + MoveOnlyInt &operator=(MoveOnlyInt &&m) noexcept { + print_move_assigned(this, m.value); + std::swap(value, m.value); + return *this; + } MoveOnlyInt(const MoveOnlyInt &) = delete; MoveOnlyInt &operator=(const MoveOnlyInt &) = delete; ~MoveOnlyInt() { print_destroyed(this); } @@ -49,11 +59,26 @@ public: class MoveOrCopyInt { public: MoveOrCopyInt() { print_default_created(this); } - MoveOrCopyInt(int v) : value{std::move(v)} { print_created(this, value); } - MoveOrCopyInt(MoveOrCopyInt &&m) { print_move_created(this, m.value); std::swap(value, m.value); } - MoveOrCopyInt &operator=(MoveOrCopyInt &&m) { print_move_assigned(this, m.value); std::swap(value, m.value); return *this; } - MoveOrCopyInt(const MoveOrCopyInt &c) { print_copy_created(this, c.value); value = c.value; } - MoveOrCopyInt &operator=(const MoveOrCopyInt &c) { print_copy_assigned(this, c.value); value = c.value; return *this; } + explicit MoveOrCopyInt(int v) : value{v} { print_created(this, value); } + MoveOrCopyInt(MoveOrCopyInt &&m) noexcept { + print_move_created(this, m.value); + std::swap(value, m.value); + } + MoveOrCopyInt &operator=(MoveOrCopyInt &&m) noexcept { + print_move_assigned(this, m.value); + std::swap(value, m.value); + return *this; + } + MoveOrCopyInt(const MoveOrCopyInt &c) { + print_copy_created(this, c.value); + // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) + value = c.value; + } + MoveOrCopyInt &operator=(const MoveOrCopyInt &c) { + print_copy_assigned(this, c.value); + value = c.value; + return *this; + } ~MoveOrCopyInt() { print_destroyed(this); } int value; @@ -61,41 +86,71 @@ public: class CopyOnlyInt { public: CopyOnlyInt() { print_default_created(this); } - CopyOnlyInt(int v) : value{std::move(v)} { print_created(this, value); } - CopyOnlyInt(const CopyOnlyInt &c) { print_copy_created(this, c.value); value = c.value; } - CopyOnlyInt &operator=(const CopyOnlyInt &c) { print_copy_assigned(this, c.value); value = c.value; return *this; } + explicit CopyOnlyInt(int v) : value{v} { print_created(this, value); } + CopyOnlyInt(const CopyOnlyInt &c) { + print_copy_created(this, c.value); + // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) + value = c.value; + } + CopyOnlyInt &operator=(const CopyOnlyInt &c) { + print_copy_assigned(this, c.value); + value = c.value; + return *this; + } ~CopyOnlyInt() { print_destroyed(this); } int value; }; PYBIND11_NAMESPACE_BEGIN(pybind11) PYBIND11_NAMESPACE_BEGIN(detail) -template <> struct type_caster<MoveOnlyInt> { - PYBIND11_TYPE_CASTER(MoveOnlyInt, _("MoveOnlyInt")); - bool load(handle src, bool) { value = MoveOnlyInt(src.cast<int>()); return true; } - static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); } +template <> +struct type_caster<MoveOnlyInt> { + PYBIND11_TYPE_CASTER(MoveOnlyInt, const_name("MoveOnlyInt")); + bool load(handle src, bool) { + value = MoveOnlyInt(src.cast<int>()); + return true; + } + static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) { + return pybind11::cast(m.value, r, p); + } }; -template <> struct type_caster<MoveOrCopyInt> { - PYBIND11_TYPE_CASTER(MoveOrCopyInt, _("MoveOrCopyInt")); - bool load(handle src, bool) { value = MoveOrCopyInt(src.cast<int>()); return true; } - static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); } +template <> +struct type_caster<MoveOrCopyInt> { + PYBIND11_TYPE_CASTER(MoveOrCopyInt, const_name("MoveOrCopyInt")); + bool load(handle src, bool) { + value = MoveOrCopyInt(src.cast<int>()); + return true; + } + static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) { + return pybind11::cast(m.value, r, p); + } }; -template <> struct type_caster<CopyOnlyInt> { +template <> +struct type_caster<CopyOnlyInt> { protected: CopyOnlyInt value; + public: - static constexpr auto name = _("CopyOnlyInt"); - bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; } - static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); } + static constexpr auto name = const_name("CopyOnlyInt"); + bool load(handle src, bool) { + value = CopyOnlyInt(src.cast<int>()); + return true; + } + static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { + return pybind11::cast(m.value, r, p); + } static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) { - if (!src) return none().release(); + if (!src) { + return none().release(); + } return cast(*src, policy, parent); } - operator CopyOnlyInt*() { return &value; } - operator CopyOnlyInt&() { return value; } - template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>; + explicit operator CopyOnlyInt *() { return &value; } + explicit operator CopyOnlyInt &() { return value; } + template <typename T> + using cast_op_type = pybind11::detail::cast_op_type<T>; }; PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(pybind11) @@ -103,22 +158,21 @@ PYBIND11_NAMESPACE_END(pybind11) TEST_SUBMODULE(copy_move_policies, m) { // test_lacking_copy_ctor py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor") - .def_static("get_one", &lacking_copy_ctor::get_one, - py::return_value_policy::copy); + .def_static("get_one", &lacking_copy_ctor::get_one, py::return_value_policy::copy); // test_lacking_move_ctor py::class_<lacking_move_ctor>(m, "lacking_move_ctor") - .def_static("get_one", &lacking_move_ctor::get_one, - py::return_value_policy::move); + .def_static("get_one", &lacking_move_ctor::get_one, py::return_value_policy::move); // test_move_and_copy_casts - m.def("move_and_copy_casts", [](py::object o) { + // NOLINTNEXTLINE(performance-unnecessary-value-param) + m.def("move_and_copy_casts", [](const py::object &o) { int r = 0; r += py::cast<MoveOrCopyInt>(o).value; /* moves */ - r += py::cast<MoveOnlyInt>(o).value; /* moves */ - r += py::cast<CopyOnlyInt>(o).value; /* copies */ - auto m1(py::cast<MoveOrCopyInt>(o)); /* moves */ - auto m2(py::cast<MoveOnlyInt>(o)); /* moves */ - auto m3(py::cast<CopyOnlyInt>(o)); /* copies */ + r += py::cast<MoveOnlyInt>(o).value; /* moves */ + r += py::cast<CopyOnlyInt>(o).value; /* copies */ + auto m1(py::cast<MoveOrCopyInt>(o)); /* moves */ + auto m2(py::cast<MoveOnlyInt>(o)); /* moves */ + auto m3(py::cast<CopyOnlyInt>(o)); /* copies */ r += m1.value + m2.value + m3.value; return r; @@ -126,30 +180,40 @@ TEST_SUBMODULE(copy_move_policies, m) { // test_move_and_copy_loads m.def("move_only", [](MoveOnlyInt m) { return m.value; }); + // Changing this breaks the existing test: needs careful review. + // NOLINTNEXTLINE(performance-unnecessary-value-param) m.def("move_or_copy", [](MoveOrCopyInt m) { return m.value; }); + // Changing this breaks the existing test: needs careful review. + // NOLINTNEXTLINE(performance-unnecessary-value-param) m.def("copy_only", [](CopyOnlyInt m) { return m.value; }); - m.def("move_pair", [](std::pair<MoveOnlyInt, MoveOrCopyInt> p) { - return p.first.value + p.second.value; - }); + m.def("move_pair", + [](std::pair<MoveOnlyInt, MoveOrCopyInt> p) { return p.first.value + p.second.value; }); m.def("move_tuple", [](std::tuple<MoveOnlyInt, MoveOrCopyInt, MoveOnlyInt> t) { return std::get<0>(t).value + std::get<1>(t).value + std::get<2>(t).value; }); m.def("copy_tuple", [](std::tuple<CopyOnlyInt, CopyOnlyInt> t) { return std::get<0>(t).value + std::get<1>(t).value; }); - m.def("move_copy_nested", [](std::pair<MoveOnlyInt, std::pair<std::tuple<MoveOrCopyInt, CopyOnlyInt, std::tuple<MoveOnlyInt>>, MoveOrCopyInt>> x) { - return x.first.value + std::get<0>(x.second.first).value + std::get<1>(x.second.first).value + - std::get<0>(std::get<2>(x.second.first)).value + x.second.second.value; - }); + m.def("move_copy_nested", + [](std::pair<MoveOnlyInt, + std::pair<std::tuple<MoveOrCopyInt, CopyOnlyInt, std::tuple<MoveOnlyInt>>, + MoveOrCopyInt>> x) { + return x.first.value + std::get<0>(x.second.first).value + + std::get<1>(x.second.first).value + + std::get<0>(std::get<2>(x.second.first)).value + x.second.second.value; + }); m.def("move_and_copy_cstats", []() { ConstructorStats::gc(); // Reset counts to 0 so that previous tests don't affect later ones: auto &mc = ConstructorStats::get<MoveOrCopyInt>(); - mc.move_assignments = mc.move_constructions = mc.copy_assignments = mc.copy_constructions = 0; + mc.move_assignments = mc.move_constructions = mc.copy_assignments = mc.copy_constructions + = 0; auto &mo = ConstructorStats::get<MoveOnlyInt>(); - mo.move_assignments = mo.move_constructions = mo.copy_assignments = mo.copy_constructions = 0; + mo.move_assignments = mo.move_constructions = mo.copy_assignments = mo.copy_constructions + = 0; auto &co = ConstructorStats::get<CopyOnlyInt>(); - co.move_assignments = co.move_constructions = co.copy_assignments = co.copy_constructions = 0; + co.move_assignments = co.move_constructions = co.copy_assignments = co.copy_constructions + = 0; py::dict d; d["MoveOrCopyInt"] = py::cast(mc, py::return_value_policy::reference); d["MoveOnlyInt"] = py::cast(mo, py::return_value_policy::reference); @@ -159,18 +223,13 @@ TEST_SUBMODULE(copy_move_policies, m) { #ifdef PYBIND11_HAS_OPTIONAL // test_move_and_copy_load_optional m.attr("has_optional") = true; - m.def("move_optional", [](std::optional<MoveOnlyInt> o) { - return o->value; - }); - m.def("move_or_copy_optional", [](std::optional<MoveOrCopyInt> o) { - return o->value; - }); - m.def("copy_optional", [](std::optional<CopyOnlyInt> o) { - return o->value; - }); - m.def("move_optional_tuple", [](std::optional<std::tuple<MoveOrCopyInt, MoveOnlyInt, CopyOnlyInt>> x) { - return std::get<0>(*x).value + std::get<1>(*x).value + std::get<2>(*x).value; - }); + m.def("move_optional", [](std::optional<MoveOnlyInt> o) { return o->value; }); + m.def("move_or_copy_optional", [](std::optional<MoveOrCopyInt> o) { return o->value; }); + m.def("copy_optional", [](std::optional<CopyOnlyInt> o) { return o->value; }); + m.def("move_optional_tuple", + [](std::optional<std::tuple<MoveOrCopyInt, MoveOnlyInt, CopyOnlyInt>> x) { + return std::get<0>(*x).value + std::get<1>(*x).value + std::get<2>(*x).value; + }); #else m.attr("has_optional") = false; #endif @@ -181,39 +240,56 @@ TEST_SUBMODULE(copy_move_policies, m) { // added later. struct PrivateOpNew { int value = 1; + private: void *operator new(size_t bytes) { void *ptr = std::malloc(bytes); - if (ptr) + if (ptr) { return ptr; - else - throw std::bad_alloc{}; + } + throw std::bad_alloc{}; } }; py::class_<PrivateOpNew>(m, "PrivateOpNew").def_readonly("value", &PrivateOpNew::value); m.def("private_op_new_value", []() { return PrivateOpNew(); }); - m.def("private_op_new_reference", []() -> const PrivateOpNew & { - static PrivateOpNew x{}; - return x; - }, py::return_value_policy::reference); + m.def( + "private_op_new_reference", + []() -> const PrivateOpNew & { + static PrivateOpNew x{}; + return x; + }, + py::return_value_policy::reference); // test_move_fallback // #389: rvp::move should fall-through to copy on non-movable objects struct MoveIssue1 { int v; - MoveIssue1(int v) : v{v} {} + explicit MoveIssue1(int v) : v{v} {} MoveIssue1(const MoveIssue1 &c) = default; MoveIssue1(MoveIssue1 &&) = delete; }; - py::class_<MoveIssue1>(m, "MoveIssue1").def(py::init<int>()).def_readwrite("value", &MoveIssue1::v); + py::class_<MoveIssue1>(m, "MoveIssue1") + .def(py::init<int>()) + .def_readwrite("value", &MoveIssue1::v); struct MoveIssue2 { int v; - MoveIssue2(int v) : v{v} {} + explicit MoveIssue2(int v) : v{v} {} MoveIssue2(MoveIssue2 &&) = default; }; - py::class_<MoveIssue2>(m, "MoveIssue2").def(py::init<int>()).def_readwrite("value", &MoveIssue2::v); + py::class_<MoveIssue2>(m, "MoveIssue2") + .def(py::init<int>()) + .def_readwrite("value", &MoveIssue2::v); + + // #2742: Don't expect ownership of raw pointer to `new`ed object to be transferred with + // `py::return_value_policy::move` + m.def( + "get_moveissue1", + [](int i) { return std::unique_ptr<MoveIssue1>(new MoveIssue1(i)); }, + py::return_value_policy::move); + m.def( + "get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move); - m.def("get_moveissue1", [](int i) { return new MoveIssue1(i); }, py::return_value_policy::move); - m.def("get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move); + // 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_>(); }); } |