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  }