Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 03, 2020 opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
This is not working as expected: > bool opCmp(string op, U)(U rhs) { As it does work with: > auto opBinary(string op, U)(U rhs) { With: > struct X { > int x; > auto opBinary(string op, U)(U rhs) { > return mixin("x "~op~" rhs"); > } > bool opCmp(string op, U)(U rhs) { > return mixin("x "~op~" rhs"); > } > } This compiles: > X(5) + 4 This does not: > X(5) < 4 Full example code: https://run.dlang.io/is/Beflkt Is this a Bug? |
November 03, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Levi | Two questions: 1) Why is opCmp returning a bool? 2) Why does opCmp have a template parameter called `op`? https://dlang.org/spec/operatoroverloading.html#compare |
November 03, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Levi | On Tuesday, 3 November 2020 at 02:55:46 UTC, Jonathan Levi wrote:
> This is not working as expected:
>> bool opCmp(string op, U)(U rhs) {
>
> As it does work with:
>> auto opBinary(string op, U)(U rhs) {
>
>
> With:
>
>> struct X {
>> int x;
>> auto opBinary(string op, U)(U rhs) {
>> return mixin("x "~op~" rhs");
>> }
>> bool opCmp(string op, U)(U rhs) {
>> return mixin("x "~op~" rhs");
>> }
>> }
>
> This compiles:
>> X(5) + 4
> This does not:
>> X(5) < 4
>
> Full example code: https://run.dlang.io/is/Beflkt
>
> Is this a Bug?
opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)
|
November 03, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to user1234 | On Tuesday, 3 November 2020 at 03:07:14 UTC, user1234 wrote:
> opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)
Um, I missed that. Man, I have some old errors in my code. I had opCmp implemented that way for a while, and apparently never tested or used it. I see that now in the spec.
|
November 03, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to user1234 | On 03.11.20 04:07, user1234 wrote:
> opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)
Doing comparison by subtracting is a cute idea, but it doesn't actually work in general because of wraparound.
Example: int.min < 1, but int.min - 1 > 0.
|
November 03, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On 11/3/20 1:56 AM, ag0aep6g wrote:
> On 03.11.20 04:07, user1234 wrote:
>> opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)
>
> Doing comparison by subtracting is a cute idea, but it doesn't actually work in general because of wraparound.
>
> Example: int.min < 1, but int.min - 1 > 0.
druntime does it for integrals smaller than int. For others, you can do:
return (a > b) - (b < a);
|
November 03, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 11/3/20 8:48 AM, Andrei Alexandrescu wrote:
> On 11/3/20 1:56 AM, ag0aep6g wrote:
>> On 03.11.20 04:07, user1234 wrote:
>>> opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)
>>
>> Doing comparison by subtracting is a cute idea, but it doesn't actually work in general because of wraparound.
>>
>> Example: int.min < 1, but int.min - 1 > 0.
>
> druntime does it for integrals smaller than int. For others, you can do:
>
> return (a > b) - (b < a);
Ehm.
return (a > b) - (a < b);
|
November 04, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to user1234 | On Tuesday, 3 November 2020 at 03:07:14 UTC, user1234 wrote:
> opCmp should return a signed integer.
No. opCmp should return a float, to have all 4 possible comparison results available:
greater (1)
lower (-1)
equal (0) and
not comparable (NaN)
Especially the last one is necessary if you like to have opCmp defined on some not completely ordered set.
|
November 04, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On Wednesday, 4 November 2020 at 09:01:21 UTC, Dominikus Dittes Scherkl wrote: > On Tuesday, 3 November 2020 at 03:07:14 UTC, user1234 wrote: > >> opCmp should return a signed integer. > No. opCmp should return a float, to have all 4 possible comparison results available: > greater (1) > lower (-1) > equal (0) and > not comparable (NaN) > > Especially the last one is necessary if you like to have opCmp defined on some not completely ordered set. opCmp can return whatever you want, as long as it is comparable with 0 using the `<`, `>`, `<=`, and `>=` operators: https://dlang.org/spec/operatoroverloading.html#compare IMO there's no reason to use a floating-point number unless you specifically need partial ordering. For the common case of a totally-ordered type, a signed integer is fine. |
November 08, 2020 Re: opCmp with template type not working. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Wednesday, 4 November 2020 at 15:51:04 UTC, Paul Backus wrote:
> opCmp can return whatever you want, [...]
> IMO there's no reason to use a floating-point number unless you specifically need partial ordering. For the common case of a totally-ordered type, a signed integer is fine.
Yeah, but int is 32 bit, same as float. So why use a type that restricts the use cases without any benefit?
Simply always use float, so you have no changes if you later detect that your type to compare is in fact _not_ totally ordered (e.g. has some special cases). And beliefe me, for most types you will earlier or later detect, that they are not totally ordered.
Today when I look, most libraries do some ugly and non-performant special casing because their comparison operators didn't handle the not-comparable case correctly. In D we can do better, as we CAN handle it. So everybody should be taught to use float as the result of opCmp. The earlier we do it correct, the better for the language!
|
Copyright © 1999-2021 by the D Language Foundation