Consider a legacy class template with overloaded addition operators +=
and +
template<class T>
class X
{
public:
X() = default;
/* implicict */ X(T v): val(v) {}
X<T>& operator+=(X<T> const& rhs) { val += rhs.val; return *this; }
X<T> operator+ (X<T> const& rhs) const { return X<T>(*this) += rhs; }
private:
T val;
};
Upon code review, it is observed that +
is implementable in terms of +=
, so why not make it a non-member (and have guaranteed symmetry for left and right arguments)?
template<class T>
class X
{
public:
X() = default;
/* implicit */ X(T v): val(v) {}
X<T>& operator+=(X<T> const& rhs) { val += rhs.val; return *this; }
private:
T val;
};
template<class T>
X<T> operator+(X<T> const& lhs, X<T> const& rhs)
{
return X<T>(lhs) += rhs;
}
It look safe enough, because all valid expression using +
and +=
retain their original semantic meaning.
Question: can the refactoring of operator+
from a member function into a non-member function break any code?
Definition of breakage (worst to best)
- new code will compile that did not compile under the old scenario
- old code will not compile that did compile under the old scenario
- new code will silently call a different
operator+
(from base class or associated namespace dragged in through ADL)