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: https://godbolt.org/z/ecaro9
>

This operator+ has "too perfect forwarding" and can break many other operators. Here it breaks an ordinary std::string concatenation:

https://godbolt.org/z/bvnd9f
 
> +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.
>
> https://godbolt.org/z/7ssTjW
>

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: https://godbolt.org/z/hseceW

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 <
>> std-discussion@lists.isocpp.org> 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@lists.isocpp.org
>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>
>>
>>
--
Std-Discussion mailing list
Std-Discussion@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion