I’m in the process of designing several classes that need to support operators !=, >, <=, and >=. These operators will be implemented in terms of operators == and <.
At this stage, I need to make a choice between inheritance¹ and forcing my consumers to use std::rel_ops² ‘manually’.
[1] Inheritance (possible implementation):
template<class T> class RelationalOperatorsImpl { protected: RelationalOperatorsImpl() {} ~RelationalOperatorsImpl() {} friend bool operator!=(const T& lhs, const T& rhs) {return !(lhs == rhs);} friend bool operator>(const T& lhs, const T& rhs) {return (rhs < lhs);} friend bool operator<=(const T& lhs, const T& rhs) {return !(rhs < lhs);} friend bool operator>=(const T& lhs, const T& rhs) {return !(lhs < rhs);} }; template<typename T> class Foo : RelationalOperatorsImpl< Foo<T> > { public: explicit Foo(const T& value) : m_Value(value) {} friend bool operator==(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value == rhs.m_Value);} friend bool operator<(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value < rhs.m_Value);} private: T m_Value; };
[2] std::rel_ops glue:
template<typename T> class Foo { public: explicit Foo(const T& value) : m_Value(value) {} friend bool operator==(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value == rhs.m_Value);} friend bool operator<(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value < rhs.m_Value);} private: T m_Value; }; void Consumer() { using namespace std::rel_ops; //Operators !=, >, >=, and <= will be instantiated for Foo<T> (in this case) on demand. }
I’m basically trying to avoid code repetition. Any thoughts as to which method ‘feels’ better?
Have you considered using boost, and having your class inherit from
boost::less_than_comparable<T>andboost::equality_comparable<T>? It is akin to your first suggestion, with some pros and cons. Pros: avoids code duplication; Cons: creates a dependency on boost.Since boost is a very common C++ library (if you don’t use it already, you should seriously consider start using it), the con factor is dimmed.