github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/pybind11/tests/test_operator_overloading.cpp (about)

     1  /*
     2      tests/test_operator_overloading.cpp -- operator overloading
     3  
     4      Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
     5  
     6      All rights reserved. Use of this source code is governed by a
     7      BSD-style license that can be found in the LICENSE file.
     8  */
     9  
    10  #include <pybind11/operators.h>
    11  #include <pybind11/stl.h>
    12  
    13  #include "constructor_stats.h"
    14  #include "pybind11_tests.h"
    15  
    16  #include <functional>
    17  
    18  class Vector2 {
    19  public:
    20      Vector2(float x, float y) : x(x), y(y) { print_created(this, toString()); }
    21      Vector2(const Vector2 &v) : x(v.x), y(v.y) { print_copy_created(this); }
    22      Vector2(Vector2 &&v) noexcept : x(v.x), y(v.y) {
    23          print_move_created(this);
    24          v.x = v.y = 0;
    25      }
    26      Vector2 &operator=(const Vector2 &v) {
    27          x = v.x;
    28          y = v.y;
    29          print_copy_assigned(this);
    30          return *this;
    31      }
    32      Vector2 &operator=(Vector2 &&v) noexcept {
    33          x = v.x;
    34          y = v.y;
    35          v.x = v.y = 0;
    36          print_move_assigned(this);
    37          return *this;
    38      }
    39      ~Vector2() { print_destroyed(this); }
    40  
    41      std::string toString() const {
    42          return "[" + std::to_string(x) + ", " + std::to_string(y) + "]";
    43      }
    44  
    45      Vector2 operator-() const { return Vector2(-x, -y); }
    46      Vector2 operator+(const Vector2 &v) const { return Vector2(x + v.x, y + v.y); }
    47      Vector2 operator-(const Vector2 &v) const { return Vector2(x - v.x, y - v.y); }
    48      Vector2 operator-(float value) const { return Vector2(x - value, y - value); }
    49      Vector2 operator+(float value) const { return Vector2(x + value, y + value); }
    50      Vector2 operator*(float value) const { return Vector2(x * value, y * value); }
    51      Vector2 operator/(float value) const { return Vector2(x / value, y / value); }
    52      Vector2 operator*(const Vector2 &v) const { return Vector2(x * v.x, y * v.y); }
    53      Vector2 operator/(const Vector2 &v) const { return Vector2(x / v.x, y / v.y); }
    54      Vector2 &operator+=(const Vector2 &v) {
    55          x += v.x;
    56          y += v.y;
    57          return *this;
    58      }
    59      Vector2 &operator-=(const Vector2 &v) {
    60          x -= v.x;
    61          y -= v.y;
    62          return *this;
    63      }
    64      Vector2 &operator*=(float v) {
    65          x *= v;
    66          y *= v;
    67          return *this;
    68      }
    69      Vector2 &operator/=(float v) {
    70          x /= v;
    71          y /= v;
    72          return *this;
    73      }
    74      Vector2 &operator*=(const Vector2 &v) {
    75          x *= v.x;
    76          y *= v.y;
    77          return *this;
    78      }
    79      Vector2 &operator/=(const Vector2 &v) {
    80          x /= v.x;
    81          y /= v.y;
    82          return *this;
    83      }
    84  
    85      friend Vector2 operator+(float f, const Vector2 &v) { return Vector2(f + v.x, f + v.y); }
    86      friend Vector2 operator-(float f, const Vector2 &v) { return Vector2(f - v.x, f - v.y); }
    87      friend Vector2 operator*(float f, const Vector2 &v) { return Vector2(f * v.x, f * v.y); }
    88      friend Vector2 operator/(float f, const Vector2 &v) { return Vector2(f / v.x, f / v.y); }
    89  
    90      bool operator==(const Vector2 &v) const { return x == v.x && y == v.y; }
    91      bool operator!=(const Vector2 &v) const { return x != v.x || y != v.y; }
    92  
    93  private:
    94      float x, y;
    95  };
    96  
    97  class C1 {};
    98  class C2 {};
    99  
   100  int operator+(const C1 &, const C1 &) { return 11; }
   101  int operator+(const C2 &, const C2 &) { return 22; }
   102  int operator+(const C2 &, const C1 &) { return 21; }
   103  int operator+(const C1 &, const C2 &) { return 12; }
   104  
   105  struct HashMe {
   106      std::string member;
   107  };
   108  
   109  bool operator==(const HashMe &lhs, const HashMe &rhs) { return lhs.member == rhs.member; }
   110  
   111  // Note: Specializing explicit within `namespace std { ... }` is done due to a
   112  // bug in GCC<7. If you are supporting compilers later than this, consider
   113  // specializing `using template<> struct std::hash<...>` in the global
   114  // namespace instead, per this recommendation:
   115  // https://en.cppreference.com/w/cpp/language/extending_std#Adding_template_specializations
   116  namespace std {
   117  template <>
   118  struct hash<Vector2> {
   119      // Not a good hash function, but easy to test
   120      size_t operator()(const Vector2 &) { return 4; }
   121  };
   122  
   123  // HashMe has a hash function in C++ but no `__hash__` for Python.
   124  template <>
   125  struct hash<HashMe> {
   126      std::size_t operator()(const HashMe &selector) const {
   127          return std::hash<std::string>()(selector.member);
   128      }
   129  };
   130  } // namespace std
   131  
   132  // Not a good abs function, but easy to test.
   133  std::string abs(const Vector2 &) { return "abs(Vector2)"; }
   134  
   135  // clang 7.0.0 and Apple LLVM 10.0.1 introduce `-Wself-assign-overloaded` to
   136  // `-Wall`, which is used here for overloading (e.g. `py::self += py::self `).
   137  // Here, we suppress the warning
   138  // Taken from: https://github.com/RobotLocomotion/drake/commit/aaf84b46
   139  // TODO(eric): This could be resolved using a function / functor (e.g. `py::self()`).
   140  #if defined(__APPLE__) && defined(__clang__)
   141  #    if (__clang_major__ >= 10)
   142  PYBIND11_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
   143  #    endif
   144  #elif defined(__clang__)
   145  #    if (__clang_major__ >= 7)
   146  PYBIND11_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
   147  #    endif
   148  #endif
   149  
   150  TEST_SUBMODULE(operators, m) {
   151  
   152      // test_operator_overloading
   153      py::class_<Vector2>(m, "Vector2")
   154          .def(py::init<float, float>())
   155          .def(py::self + py::self)
   156          .def(py::self + float())
   157          .def(py::self - py::self)
   158          .def(py::self - float())
   159          .def(py::self * float())
   160          .def(py::self / float())
   161          .def(py::self * py::self)
   162          .def(py::self / py::self)
   163          .def(py::self += py::self)
   164          .def(py::self -= py::self)
   165          .def(py::self *= float())
   166          .def(py::self /= float())
   167          .def(py::self *= py::self)
   168          .def(py::self /= py::self)
   169          .def(float() + py::self)
   170          .def(float() - py::self)
   171          .def(float() * py::self)
   172          .def(float() / py::self)
   173          .def(-py::self)
   174          .def("__str__", &Vector2::toString)
   175          .def("__repr__", &Vector2::toString)
   176          .def(py::self == py::self)
   177          .def(py::self != py::self)
   178          .def(py::hash(py::self))
   179          // N.B. See warning about usage of `py::detail::abs(py::self)` in
   180          // `operators.h`.
   181          .def("__abs__", [](const Vector2 &v) { return abs(v); });
   182  
   183      m.attr("Vector") = m.attr("Vector2");
   184  
   185      // test_operators_notimplemented
   186      // #393: need to return NotSupported to ensure correct arithmetic operator behavior
   187      py::class_<C1>(m, "C1").def(py::init<>()).def(py::self + py::self);
   188  
   189      py::class_<C2>(m, "C2")
   190          .def(py::init<>())
   191          .def(py::self + py::self)
   192          .def("__add__", [](const C2 &c2, const C1 &c1) { return c2 + c1; })
   193          .def("__radd__", [](const C2 &c2, const C1 &c1) { return c1 + c2; });
   194  
   195      // test_nested
   196      // #328: first member in a class can't be used in operators
   197      struct NestABase {
   198          int value = -2;
   199      };
   200      py::class_<NestABase>(m, "NestABase")
   201          .def(py::init<>())
   202          .def_readwrite("value", &NestABase::value);
   203  
   204      struct NestA : NestABase {
   205          int value = 3;
   206          NestA &operator+=(int i) {
   207              value += i;
   208              return *this;
   209          }
   210      };
   211      py::class_<NestA>(m, "NestA")
   212          .def(py::init<>())
   213          .def(py::self += int())
   214          .def(
   215              "as_base",
   216              [](NestA &a) -> NestABase & { return (NestABase &) a; },
   217              py::return_value_policy::reference_internal);
   218      m.def("get_NestA", [](const NestA &a) { return a.value; });
   219  
   220      struct NestB {
   221          NestA a;
   222          int value = 4;
   223          NestB &operator-=(int i) {
   224              value -= i;
   225              return *this;
   226          }
   227      };
   228      py::class_<NestB>(m, "NestB")
   229          .def(py::init<>())
   230          .def(py::self -= int())
   231          .def_readwrite("a", &NestB::a);
   232      m.def("get_NestB", [](const NestB &b) { return b.value; });
   233  
   234      struct NestC {
   235          NestB b;
   236          int value = 5;
   237          NestC &operator*=(int i) {
   238              value *= i;
   239              return *this;
   240          }
   241      };
   242      py::class_<NestC>(m, "NestC")
   243          .def(py::init<>())
   244          .def(py::self *= int())
   245          .def_readwrite("b", &NestC::b);
   246      m.def("get_NestC", [](const NestC &c) { return c.value; });
   247  
   248      // test_overriding_eq_reset_hash
   249      // #2191 Overriding __eq__ should set __hash__ to None
   250      struct Comparable {
   251          int value;
   252          bool operator==(const Comparable &rhs) const { return value == rhs.value; }
   253      };
   254  
   255      struct Hashable : Comparable {
   256          explicit Hashable(int value) : Comparable{value} {};
   257          size_t hash() const { return static_cast<size_t>(value); }
   258      };
   259  
   260      struct Hashable2 : Hashable {
   261          using Hashable::Hashable;
   262      };
   263  
   264      py::class_<Comparable>(m, "Comparable").def(py::init<int>()).def(py::self == py::self);
   265  
   266      py::class_<Hashable>(m, "Hashable")
   267          .def(py::init<int>())
   268          .def(py::self == py::self)
   269          .def("__hash__", &Hashable::hash);
   270  
   271      // define __hash__ before __eq__
   272      py::class_<Hashable2>(m, "Hashable2")
   273          .def("__hash__", &Hashable::hash)
   274          .def(py::init<int>())
   275          .def(py::self == py::self);
   276  
   277      // define __eq__ but not __hash__
   278      py::class_<HashMe>(m, "HashMe").def(py::self == py::self);
   279  
   280      m.def("get_unhashable_HashMe_set", []() { return std::unordered_set<HashMe>{{"one"}}; });
   281  }