mercredi 1 juillet 2015

Very automatic operator generator in C++

C++ has a nice idiom that allows one to write classes that automatically fulfill certain relations between operators. For example this allows to define operator== and not bother to defined operator!= as well. This is the idea behind Boost.Operators.

This is an example:

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

This class can used repeatedly to enforce consistent logic between == and != (and avoid errors)

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 !=
}

Now, I want to go one level further and have a class similar to equally_comparable and define the function the other function. For example if operator== is defined then define operator!= (like above), but also viceversa.

The first naive attempt works

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);}
};

because only one of the two functions need to be defined in struct A (either operator== or operator!=). However it is dangerous because if one forget to define either operator in A there is an infinite recursion (and a runtime segfault). It also looks fragile.

Is is possible to improve over this and detect that at least one is defined in the derived class at compile time? or more generally is there a generic way to have a class that generates the missing operators? (i.e. a step beyond Boost.Operators).

Aucun commentaire:

Enregistrer un commentaire