Implementing C++ relational operators generator Once you define the &lt; operator, you can have an estimation of how the rest of relational operators behave. I'm trying to implement a way to do that for my classes. 

What I want is to define only the &lt; and the rest of the operators to be defaulted implicitly. What I've got so far is this design, which I'll elaborate on further down:

template&lt;typename T&gt;
struct relational
{
    friend bool operator&gt; (T const &amp;lhs, T const &amp;rhs) { return rhs &lt; lhs; }
    friend bool operator==(T const &amp;lhs, T const &amp;rhs) { return !(lhs &lt; rhs || lhs &gt; rhs); }
    friend bool operator!=(T const &amp;lhs, T const &amp;rhs) { return !(rhs == lhs); }
    friend bool operator&lt;=(T const &amp;lhs, T const &amp;rhs) { return !(rhs &lt; lhs); }
    friend bool operator&gt;=(T const &amp;lhs, T const &amp;rhs) { return !(lhs &lt; rhs); }
};


So for a class that implements the &lt; operator it would just take inheriting from relational to have the rest of the operators defaulted. 

struct foo : relational&lt;foo&gt;
{ 
    // implement &lt; operator here
};



Are there any alternative, better designs? 
Is there a time bomb in this code? 
While trying to use this code with classes that already defined one of { >, ==, !=, &lt;=, >= } I had ambiguity problems. The implementation I opted for (also the one existing in the linked Github repository) is tweaked like so 

// inside the relational struct
friend bool operator&gt;(relational const &amp;lhs, relational const &amp;rhs)
{ // functions that involve implicit conversion are less favourable in overload resolution
        return (T const&amp;)rhs &lt; (T const&amp;)lhs; 
}



Are my problems over with this trick?

Here's a demo of the code working.
The problem I see is that it requires that the class be derived from relational, which is not a very durable design.  Instead, why not use the fact that "substitution failure is not an error" (which has the regrettable but commonly used abbreviation SFINAE). the use of real functions is preferred over the instantiation of templates.  That is, if an operator&lt;= actually exists, the templated form will be ignored.  That might look like this:

template&lt;typename T&gt;
bool operator&gt; (T const &amp;lhs, T const &amp;rhs) { return !(lhs &lt;= rhs); }
template&lt;typename T&gt;
bool operator&lt; (T const &amp;lhs, T const &amp;rhs) { return !(lhs &gt;= rhs); }
template&lt;typename T&gt;
bool operator==(T const &amp;lhs, T const &amp;rhs) { return lhs &lt;= rhs &amp;&amp; lhs &gt;= rhs; }
template&lt;typename T&gt;
bool operator!=(T const &amp;lhs, T const &amp;rhs) { return !(rhs == lhs); }
template&lt;typename T&gt;
bool operator&lt;=(T const &amp;lhs, T const &amp;rhs) { return lhs &lt; rhs || (!(rhs &lt; lhs)); }
template&lt;typename T&gt;
bool operator&gt;=(T const &amp;lhs, T const &amp;rhs) { return lhs &gt; rhs || (!(rhs &gt; lhs)); }


Note that the differences are that I've made each comparison operator its own template and that I've added one for &lt; and defined &lt;= and &gt;= in terms of &lt; and &gt; respectively.

The result is that if any of the comparisons &lt;, &lt;=, &gt; or &gt;= are defined, then all of the other comparisons are also available.

Edit: I should probably have pointed out why this is different from std::rel_ops.  With std::rel_ops, in order to have all six relative operators, you must define operator&lt; and operator==.  With this scheme, however, as long as at least one of the ordering operators is defined, all others will also be available.  This is due to the way these templates are deliberately circularly defined.  That is, &gt; is defined in terms of &lt;= which is defined using &lt; which is defined using &gt;= which is defined using &gt;.  This arguably adds flexibility, but it also means that it's possible that the performance is not as good because a comparison may go through several templated function instantiations.  

Further, if none of those operators is defined, that circular definition will mean infinite recursion at runtime until your stack is exhausted, putting this set of templates into the category of "perhaps more dangerous than clever" so Caveat lector.