Am 01.09.2020 um 02:51 schrieb Jefferson Carpenter via Std-Discussion:
> On 8/30/2020 12:35 AM, Jeremy Ong via Std-Discussion wrote:
>> Perhaps a type trait is a suitable alternative for this (as opposed to
>> introducing yet another keyword that decorates a function signature).
>> For
>> example:

This operator+ has "too perfect forwarding" and can break many other operators. Here it breaks an ordinary std::string concatenation:
> +1
> Also use std::enable_if instead of a static_assert in the function
> body.  This takes advantage of SFINAE so that you can write
> `does_commute` for some types, `does_anticommute` for other types, etc.

This isn't quite right. The "template <..., std::enable_if_t<...>>" does take the template out of overload resolution when the enable_if expression is false. But when the expression is true, it declares a non-type template parameter with type void, which is not allowed. The godbolt link doesn't notice the issue because check_commute now calls the original specific operator+(complex, float), not the template. One simple fix: Make the type int instead, and add a default template argument, as in "template <..., std::enable_if_t<..., int> = 0>". Demo:

I also added std::forward for perfect forwarding. This might help for an underlying function like X operator+(X x, const Y& y) { x += y; return x; }
>> On Sat, Aug 29, 2020 at 6:03 PM Tobias W. via Std-Discussion <
>>> wrote:
>>> Hi everyone!
>>> I am coming with a mathematical and embedded systems background and
>>> there is something that bothered me since I started programming.
>>> Firstly, I would like to explain the problem with an example that
>>> occurs
>>> often in slightly different but similar ways.
>>> Secondly, I will propose a possible solution.
>>> Of course, I would love to hear your thoughts.
>>> So let's imagine we have three classes.
>>>          class Real{
>>>                 double value;
>>>                ...
>>>          };
>>>          class Imag{
>>>                double value;
>>>                 ...
>>>          }
>>>          class Complex{
>>>                 double Im;
>>>                 double Re;
>>>                ...
>>>          };
>>> Then if I was to write functions, for example, an add function or
>>> operator+ and would like to add them in all possible permutations of
>>> arguments.
>>> This means, that I would have to write all those following functions,
>>> just to add them:
>>>          Complex operator+ (Real a, Imag b);
>>>          Complex operator+ (Imag b, Real a); // Mirrored function
>>>          Complex operator+ (Real a, Complex b);
>>>          Complex operator+ ( Complex b, Real a); //Mirrored function
>>>          Complex operator+ (Imag a, Complex b);
>>>         Complex operator+ ( Complex b, Imag a); //Mirrored function
>>>   From a mathematical point of view, all mirrored functions are
>>> obsolete,
>>> because the intent has already been stated in the function above.
>>> Furthermore, each mirrored function will use additional program memory
>>> and this can become an issue on embedded devices.
>>> Therefore I would like to introduce the idea of the expression
>>> "commutative" that can be added to functions.
>>> The commutative expression will tell the compiler that he can switch
>>> the
>>> parameters that will be passed to a function.
>>> Following this, the keyword will only be allowed for functions that
>>> possess two and only two parameters.
>>> Then the example from above may look something like this:
>>>         commutative Complex operator+ (Real a, Imag b);
>>>         commutative Complex operator+ (Real a, Complex b);
>>>         commutative Complex operator+ (Imag a, Complex b);
>>> If the compiler comes across a statement like below, he is allowed to
>>> restructure the code.
>>>       Complex =  Complex * Imag + Real;
>>> will change to:
>>>       Complex = Real + Imag * Complex;
>>> and now the three commutative functions can be used to process this
>>> command.
>>> This is far less to write, the intent is clear, fewer functions are
>>> used
>>> and I only pay for the programme memory I need.
>>> This, of course, is not allowed to change the evaluation order of
>>> operator* and operator+. The operator* will always be evaluated first
>>> and the operator+ will always work with its result.
>>> The operator+ is not allowed to steal one of the operator* 's
>>> parameters.
>>> commutative will, of course, be available for all functions that take 2
>>> parameters, not just operators.
>>> These are my thoughts, as already stated above, I would love to hear
>>> yours.
>>> Sincerely,
>>> Tobias Wallner
>>> --
>>> Std-Discussion mailing list
Std-Discussion mailing list