If this is not obvious from the description in the comment:
template <typename T> struct Comparable { friend bool operator!=(T const & lhs, T const & rhs) { return !(lhs == rhs); } friend bool operator> (T const & lhs, T const & rhs) { return rhs < lhs; }
When the compiler encounters the search MyType a, b; a > b; MyType a, b; a > b; for the operator, it will end the execution of the ADL, which will look inside MyType and Comparable<MyType> (since this is the base), where it will find the implementation you need: bool operator>(MyType const&, MyType const&) .
Operators that are free functions allow a definition that is outside the type being compared (in this case, the database), making these operators available only through ADL (one of the two arguments must be Comparable<MyType> ). Using a free function also provides type symmetry, the compiler will allow implicit conversions on both sides, where in the case of a member function, it allows conversions only on the right side of the operator.
For completeness, you can do another trick: provide operators in the form of templates in the namespace along with a tag that can be used to cast this namespace for ADL purposes:
namespace operators { template <typename T> bool operator>(T const & lhs, T const & rhs) { return rhs < lhs; }
The trick is basically the same, except that in this case the operators are not inside the database, but in the namespace that is associated with it. This solution is slightly less enjoyable than the previous one, as it is open to various forms of abuse, including using namespace operators; that will make boilerplate operators available for all types.
source share