
On Mon, Nov 13, 2017 at 9:20 AM, Beman Dawes via Boost <boost@lists.boost.org> wrote:
Peter Sommerlad, committee member and C++Now presenter who often proposes additions to fill in holes in the standard library, asked me:
Are you aware of anybody who tried to provide a boost::operators style of automatically providing additional operators with a single base class that through SFINAE injects all possible operators based on the ones defined in the template parameter? This won't give you the control of the current boost::operators, but would be much easier to teach.
For example
struct Me : make_operators_for<Me>{ Me& operator+=(Me const&); // You get + bool operator<(Me const&) const; // You get all relops (<=> will make that obsolete) Me& operator++(); // you get postfix //etc. };
Today we have the facilities and compilers to make that happen.
What do you think? Who should I ask?
Anyone doing any work on operators or have any thoughts about updating boost::operators?
At one point I made a CRTP base that conditionally provides operators, but only for comparisons (==, !=, <, >, <=, >=). In order to not negatively impact compilation and to preserve the operators as inline, non-template friends, I had to make some different design decisions from Boost.Operators. First, in order to avoid subtleties, when you inherit from the CRTP base you specify "dependencies" in addition to the ChildType. These dependencies, in practice, are a list of all of the other bases and members of the ChildType that might contribute to equivalence and ordering. The operators are then conditionally provided by the CRTP base if and only if any required operators are callable for each dependency (i.e. == and != are only generated if the following is valid for each dependency (std::declval<Dependency const&>() == std::declval<Dependency const&>()). One other difference from Boost.Operators is that when inheriting from the base, you do *not* implement operator== and operator<. Instead, the customization point methodology was more similar to the boost::iterator_core_access technique -- the ChildType implements "equals" and "less_than" (names are actually obfuscated with "namespace" prefixes for the customization point). The point of this is that the base type is the one that conditionally generates == and <, in addition to the other operators, based on the result from the dependency checks, meaning that the ChildType is free to implement the customization points totally unconstrained. Because of this, the ChildType doesn't have to do any metaprogramming or manual SFINAE and the operators that are generated are all inline, non-template friends. I also want to echo Vicente's concerns about trying to generate all operators. Ultimately, I do believe that they are better off explicitly requested as-in Boost.Operators. In addition to that, properly checking if the ChildType supports the necessary dependent operators is not free, and it's also easy to inadvertently trigger the check to be instantiated while the the ChildType is still incomplete if the check takes place in a template that must be considered during overload resolution by unrelated calls. I suspect that these approaches will have too many subtleties to be useful in practice, though it'd be nice to be proven wrong. -- Matt Calabrese