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)
inline
. – Hypabyssalinline
is not required here. In any case, for argument's sake, assume the code is all header-only (updated in the question) – Sacculusinline
is redundant; template functions implicitly instantiated have implicit inline linkage. – Transsonicinline
is primarily used not to indicate that the function should be inlined (the standard does not require compilers to honorinline
in this way) but rather to indicate that the ODR does not apply (the function is allowed to be defined in multiple translation units without error). Since implicit instantiations of templates are already exempt from the ODR,inline
doesn't really accomplish anything. They are not the same thing but they have the same effect (again, with regard to implicit instantiations). – Transsonic+
as a member function somewhere:X<Foo> z = x.operator+(y);
But this is not related to ADL, and also extremely unlikely to encounter that. – Ackler