
Christopher Eltschka ha scritto:
Ah, sorry, although I looked into boost before writing the mail, I somehow missed that, despite its obvious name. However I see that the boost version forces you to explicitly repeat the class name, i.e. you have to write
class X: boost::operators<X> { ... };
instead of just
class X: boost::operators { ... };
Is there any specific reason to do so? After all, it seems to work well without that extra burden. Any specific example where I could get problems with my version?
The template parameter is needed because boost::operator actually provides an in-class implementation of the required operators, instead of just making them visible through ADL as in your approach (which is indeed quite clever, if I can say so). I can see the following differences between the two approaches: 1) granularity: well, that's not really an issue, because you could easily elaborate your approach to avoid defining unwanted operators (for example: dont' define operator> if it's not needed) 2) with your approach you can't define operators which must be member functions, that is operator[] and operator-> (that's not too bad, anyway) 3) type deduction rules are different, because boost operators are regular functions, while your operators are function templates. Consider this: struct base : /* EITHER boost::equality_comparable<base> OR rel::ops HERE */ { // ... friend bool operator==(const base&, const base&); }; struct derived : base { }; void test() { base b1, b2; derived d1, d2; b1 != b2; // ok in both approaches d1 != d2; // ok in both approaches b1 != d1; // ok with boost: d1 is implicitly converted to const base& // illegal with rel::ops: can't deduce template argument } This is not terribly bad, but it's enough to make me accept the annoyance of duplicating the class name. But that's just my opinion ;) Also you have to consider there are still a lot of compilers around that don't support ADL correctly, so, despite the formal correctness, there might be some hidden portability problems. Ganesh