www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can opCmp return a 'long' instead of 'int'?

reply "Saurabh Das" <saurabh.das gmail.com> writes:
Hello,

The call signature for opCmp in a struct is:

struct S {
   int opCmp(ref const S s) const { ... }
}

int opCmp(ref const S s) const { return _val - s._val; }

This works fine if _val is 'int'. However, if _val is 'long' then 
subtracting 2 longs may not result in an int - and therefore I 
would have to replace the subtraction above with 2 comparison 
operators.

My question is: Can I rewrite opCmp to return a 'long', like:

struct S {
   long opCmp(ref const S s) const { return _val - s.val; }
}

This does compile and run correctly, but are there any hidden 
assumptions or requirements on the return value of opCmp that I 
should be aware of? Is there any reason that doing this may be 
not be wise?

Thanks,
Saurabh
Feb 16 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/16/2014 02:59 PM, Saurabh Das wrote:
 This does compile and run correctly, but are there any hidden
 assumptions or requirements on the return value of opCmp that I should
 be aware of? Is there any reason that doing this may be not be wise?
No, this is fine.
Feb 16 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/16/2014 04:13 PM, Timon Gehr wrote:
 On 02/16/2014 02:59 PM, Saurabh Das wrote:
 This does compile and run correctly, but are there any hidden
 assumptions or requirements on the return value of opCmp that I should
 be aware of? Is there any reason that doing this may be not be wise?
No, this is fine.
To be more precise: Returning long is fine. The subtraction trick does not work in general regardless of return type: import std.stdio; struct S{ int d; int opCmp(S r){ return d - r.d; } } void main(){ assert(S(1)<S(2)); // passes. ok. assert(S(int.min)>S(int.max)); // passes. oops. }
Feb 16 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Timon Gehr:

     assert(S(1)<S(2)); // passes. ok.
     assert(S(int.min)>S(int.max)); // passes. oops.
A possible solution is to add to Phobos (unless it's already there) a variadic templated funcion cmpBuilder() that accepts an even number of arguments, that are seen as pairs. Usage example: struct Foo { int x, y; string s; int opCmp(in ref Foo r) { return cmpBuilder(x, r.x, y.abs, r.y.abs, s, r.s); } } Is this worth adding to Phobos? Bye, bearophile
Feb 16 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 02/16/2014 04:40 PM, bearophile wrote:
 Timon Gehr:

     assert(S(1)<S(2)); // passes. ok.
     assert(S(int.min)>S(int.max)); // passes. oops.
A possible solution is to add to Phobos (unless it's already there) a variadic templated funcion cmpBuilder() that accepts an even number of arguments, that are seen as pairs. Usage example: struct Foo { int x, y; string s; int opCmp(in ref Foo r) { return cmpBuilder(x, r.x, y.abs, r.y.abs, s, r.s); } } Is this worth adding to Phobos? Bye, bearophile
IMO no (lots of repetition), but forwarding opCmp is: struct Foo{ int x,y; string s; private property order(){ return tuple(x, abs(y), s); } mixin OrderBy!order; } Furthermore, the language should be updated such that the built-in types are not special w.r.t. operators. Eg: 1.opBinary!"+"(2) 1.opCmp(2) should work. The following should be supported as well: struct Foo{ int x,y; string s; mixin OrderBy!(()=>tuple(x, abs(y), s)); } (Currently DMD bans function literals as members.)
Feb 16 2014
prev sibling parent "Saurabh Das" <saurabh.das gmail.com> writes:
On Sunday, 16 February 2014 at 15:19:08 UTC, Timon Gehr wrote:
 On 02/16/2014 04:13 PM, Timon Gehr wrote:
 On 02/16/2014 02:59 PM, Saurabh Das wrote:
 This does compile and run correctly, but are there any hidden
 assumptions or requirements on the return value of opCmp that 
 I should
 be aware of? Is there any reason that doing this may be not 
 be wise?
No, this is fine.
To be more precise: Returning long is fine. The subtraction trick does not work in general regardless of return type: import std.stdio; struct S{ int d; int opCmp(S r){ return d - r.d; } } void main(){ assert(S(1)<S(2)); // passes. ok. assert(S(int.min)>S(int.max)); // passes. oops. }
Right. I didn't expect that! So I shouldn't use it anyway. Thanks! Saurabh
Feb 16 2014