@@ -155,23 +155,23 @@ class object_api : public pyobject_tag {
155155 object operator -() const ;
156156 object operator ~() const ;
157157 object operator +(object_api const &other) const ;
158- object operator +=(object_api const &other) const ;
158+ object operator +=(object_api const &other);
159159 object operator -(object_api const &other) const ;
160- object operator -=(object_api const &other) const ;
160+ object operator -=(object_api const &other);
161161 object operator *(object_api const &other) const ;
162- object operator *=(object_api const &other) const ;
162+ object operator *=(object_api const &other);
163163 object operator /(object_api const &other) const ;
164- object operator /=(object_api const &other) const ;
164+ object operator /=(object_api const &other);
165165 object operator |(object_api const &other) const ;
166- object operator |=(object_api const &other) const ;
166+ object operator |=(object_api const &other);
167167 object operator &(object_api const &other) const ;
168- object operator &=(object_api const &other) const ;
168+ object operator &=(object_api const &other);
169169 object operator ^(object_api const &other) const ;
170- object operator ^=(object_api const &other) const ;
170+ object operator ^=(object_api const &other);
171171 object operator <<(object_api const &other) const ;
172- object operator <<=(object_api const &other) const ;
172+ object operator <<=(object_api const &other);
173173 object operator >>(object_api const &other) const ;
174- object operator >>=(object_api const &other) const ;
174+ object operator >>=(object_api const &other);
175175
176176 PYBIND11_DEPRECATED (" Use py::str(obj) instead" )
177177 pybind11::str str () const ;
@@ -334,12 +334,15 @@ class object : public handle {
334334 }
335335
336336 object &operator =(const object &other) {
337- other.inc_ref ();
338- // Use temporary variable to ensure `*this` remains valid while
339- // `Py_XDECREF` executes, in case `*this` is accessible from Python.
340- handle temp (m_ptr);
341- m_ptr = other.m_ptr ;
342- temp.dec_ref ();
337+ // Skip inc_ref and dec_ref if both objects are the same
338+ if (!this ->is (other)) {
339+ other.inc_ref ();
340+ // Use temporary variable to ensure `*this` remains valid while
341+ // `Py_XDECREF` executes, in case `*this` is accessible from Python.
342+ handle temp (m_ptr);
343+ m_ptr = other.m_ptr ;
344+ temp.dec_ref ();
345+ }
343346 return *this ;
344347 }
345348
@@ -353,6 +356,20 @@ class object : public handle {
353356 return *this ;
354357 }
355358
359+ #define PYBIND11_INPLACE_OP (iop ) \
360+ object iop (object_api const &other) { return operator =(handle::iop (other)); }
361+
362+ PYBIND11_INPLACE_OP (operator +=)
363+ PYBIND11_INPLACE_OP (operator -=)
364+ PYBIND11_INPLACE_OP (operator *=)
365+ PYBIND11_INPLACE_OP (operator /=)
366+ PYBIND11_INPLACE_OP (operator |=)
367+ PYBIND11_INPLACE_OP (operator &=)
368+ PYBIND11_INPLACE_OP (operator ^=)
369+ PYBIND11_INPLACE_OP (operator <<=)
370+ PYBIND11_INPLACE_OP (operator >>=)
371+ #undef PYBIND11_INPLACE_OP
372+
356373 // Calling cast() on an object lvalue just copies (via handle::cast)
357374 template <typename T>
358375 T cast () const &;
@@ -2364,26 +2381,35 @@ bool object_api<D>::rich_compare(object_api const &other, int value) const {
23642381 return result; \
23652382 }
23662383
2384+ #define PYBIND11_MATH_OPERATOR_BINARY_INPLACE (iop, fn ) \
2385+ template <typename D> \
2386+ object object_api<D>::iop(object_api const &other) { \
2387+ object result = reinterpret_steal<object>(fn (derived ().ptr (), other.derived ().ptr ())); \
2388+ if (!result.ptr ()) \
2389+ throw error_already_set (); \
2390+ return result; \
2391+ }
2392+
23672393PYBIND11_MATH_OPERATOR_UNARY (operator ~, PyNumber_Invert)
23682394PYBIND11_MATH_OPERATOR_UNARY(operator -, PyNumber_Negative)
23692395PYBIND11_MATH_OPERATOR_BINARY(operator +, PyNumber_Add)
2370- PYBIND11_MATH_OPERATOR_BINARY (operator +=, PyNumber_InPlaceAdd)
2396+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator +=, PyNumber_InPlaceAdd)
23712397PYBIND11_MATH_OPERATOR_BINARY(operator -, PyNumber_Subtract)
2372- PYBIND11_MATH_OPERATOR_BINARY (operator -=, PyNumber_InPlaceSubtract)
2398+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator -=, PyNumber_InPlaceSubtract)
23732399PYBIND11_MATH_OPERATOR_BINARY(operator *, PyNumber_Multiply)
2374- PYBIND11_MATH_OPERATOR_BINARY (operator *=, PyNumber_InPlaceMultiply)
2400+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator *=, PyNumber_InPlaceMultiply)
23752401PYBIND11_MATH_OPERATOR_BINARY(operator /, PyNumber_TrueDivide)
2376- PYBIND11_MATH_OPERATOR_BINARY (operator /=, PyNumber_InPlaceTrueDivide)
2402+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator /=, PyNumber_InPlaceTrueDivide)
23772403PYBIND11_MATH_OPERATOR_BINARY(operator |, PyNumber_Or)
2378- PYBIND11_MATH_OPERATOR_BINARY (operator |=, PyNumber_InPlaceOr)
2404+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator |=, PyNumber_InPlaceOr)
23792405PYBIND11_MATH_OPERATOR_BINARY(operator &, PyNumber_And)
2380- PYBIND11_MATH_OPERATOR_BINARY (operator &=, PyNumber_InPlaceAnd)
2406+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator &=, PyNumber_InPlaceAnd)
23812407PYBIND11_MATH_OPERATOR_BINARY(operator ^, PyNumber_Xor)
2382- PYBIND11_MATH_OPERATOR_BINARY (operator ^=, PyNumber_InPlaceXor)
2408+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator ^=, PyNumber_InPlaceXor)
23832409PYBIND11_MATH_OPERATOR_BINARY(operator <<, PyNumber_Lshift)
2384- PYBIND11_MATH_OPERATOR_BINARY (operator <<=, PyNumber_InPlaceLshift)
2410+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator <<=, PyNumber_InPlaceLshift)
23852411PYBIND11_MATH_OPERATOR_BINARY(operator >>, PyNumber_Rshift)
2386- PYBIND11_MATH_OPERATOR_BINARY (operator >>=, PyNumber_InPlaceRshift)
2412+ PYBIND11_MATH_OPERATOR_BINARY_INPLACE (operator >>=, PyNumber_InPlaceRshift)
23872413
23882414#undef PYBIND11_MATH_OPERATOR_UNARY
23892415#undef PYBIND11_MATH_OPERATOR_BINARY
0 commit comments