www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Custom type creation guidelines

reply rumbu <rumbu rumbu.ro> writes:
Let's suppose that I want to implement a custom arithmetic type. 
Looking through phobos at Complex, BigInt, HalfFloat, Variant, 
etc, there is no consistent or idiomatic way to implement various 
operators or functions on custom types.

1) Regarding unary operator overloading, what's the best way to 
implement them?

auto ref opUnary(string op)() if (op == "+") { ... }
auto ref opUnary(string op : "+")() if (op == "+") { ... }
auto ref opUnary(string op)() { static if (op == "+") { } else 
... }

2) Regarding binary operator overloading, question 1 apply also, 
but there is more: what's the best signature?

ref T opBinary(string op, T)(auto const ref T rhs) { ... }
inout(T) opBinary(string op, T)(inout(T) rhs) { ... }
ref T opBinary(string op, T)(T rhs) { ... }

3) Regarding comparison operators:
- is there a way to have the same result for != and == (similar 
to float nans)
- is there a way to return the same result for <, <=, >=, > 
(similar to float nans)
- is there a way to overload float comparison operators?

4) regarding casting:
- we have opCast(T) to convert my custom type to type T. Is there 
any method to overload the casting operation from a built in 
type, e.g. cast(MyType)(int)?

5) Any other guidelines?

Thanks.
Jan 06 2016
parent John Colvin <john.loughran.colvin gmail.com> writes:
On Wednesday, 6 January 2016 at 18:38:50 UTC, rumbu wrote:
 Let's suppose that I want to implement a custom arithmetic 
 type. Looking through phobos at Complex, BigInt, HalfFloat, 
 Variant, etc, there is no consistent or idiomatic way to 
 implement various operators or functions on custom types.

 1) Regarding unary operator overloading, what's the best way to 
 implement them?

 auto ref opUnary(string op)() if (op == "+") { ... }
 auto ref opUnary(string op : "+")() if (op == "+") { ... }
 auto ref opUnary(string op)() { static if (op == "+") { } else 
 ... }
It depends, do you want to do it all in one function? It's up to the author to decide. using `:` or `if` doesn't matter here.
 2) Regarding binary operator overloading, question 1 apply 
 also, but there is more: what's the best signature?

 ref T opBinary(string op, T)(auto const ref T rhs) { ... }
 inout(T) opBinary(string op, T)(inout(T) rhs) { ... }
 ref T opBinary(string op, T)(T rhs) { ... }
Whatever works for your particular types and expresses the behaviour you want. I would suggest that returning by ref from opBinary is weird, but maybe you want/need that. Maybe your comparisons require modifying both objects, maybe they don't. There's no straightforward answer here.
 3) Regarding comparison operators:
 - is there a way to have the same result for != and == (similar 
 to float nans)
That's not how it works: assert ((float.nan != float.nan) == !(float.nan == float.nan));
 - is there a way to return the same result for <, <=, >=, > 
 (similar to float nans)
Hmmm... not sure about that. nans are a pain.
 - is there a way to overload float comparison operators?
I thought those were deprecated?
 4) regarding casting:
 - we have opCast(T) to convert my custom type to type T. Is 
 there any method to overload the casting operation from a built 
 in type, e.g. cast(MyType)(int)?
Don't think so. Perhaps we need an opCastFrom.
Jan 07 2016