Generador de operador muy automático en C ++

C ++ tiene un lenguaje agradable que permite escribir clases que cumplen automáticamente ciertas relaciones entre operadores. Por ejemplo, esto permite definiroperator== y no molestar a definidooperator!= también. Esta es la idea detrás de Boost.Operators.

Esto es un ejemplo:

template<class Self> // this class is defined only once
struct equally_comparable{
    friend bool operator!=(Self const& s1, Self const& s2){return !(s1==s2);}
};

Esta clase se puede usar repetidamente para imponer una lógica consistente entre== y!= (y evitar errores)

struct A : equally_comparable<A>{ // 
    int value;
    A(int v) : value(v){}
    friend bool operator==(A const& a1, A const& a2){return a1.value == a2.value;}
};

int main(){

    A a1{4};
    A a2{4};
    assert(a1 == a2);
    A a3{5};
    assert(a1 != a3); // uses automatically generated operator !=
}

Ahora, quiero ir un nivel más allá y tener una clase similar aequally_comparable y definir elotro función. Por ejemplo sioperator== se define luego defineoperator!= (como arriba), pero también viceversa.

El primer intento ingenuo funciona

template<class Self>
struct equally_comparable{
    friend bool operator!=(Self const& s1, Self const& s2){return !(s1==s2);}
    friend bool operator==(Self const& s1, Self const& s2){return !(s1!=s2);}
};

porque solo una de las dos funciones debe definirse enstruct A (ya seaoperator== ooperator!=) Sin embargo, es peligroso porque si uno olvida definir cualquiera de los operadores enA Hay una recursión infinita (y una segfault de tiempo de ejecución). También se ve frágil.

¿Es posible mejorar esto y detectar que al menos uno está definido en la clase derivada en tiempo de compilación? o más generalmente, ¿hay una forma genérica de tener una clase que genere los operadores que faltan? (es decir, un paso más allá de Boost.Operators).

Respuestas a la pregunta(1)

Su respuesta a la pregunta