user defined implicit casts
Tristam MacDonald
swiftcoder at gmail.com
Fri Jul 27 14:17:37 PDT 2007
While I would like to see this, I wopuld like to see a logical extension of the last part even more: non-member operator overloads. This is an incredibly neat feature from C++ that was lost somewhere along the way, but I don't know if it was intentional or not...
Ender KaShae Wrote:
> I have become aware that in D it is possible to create wrapper classes that can intermingle with primitave types for example:
>
> /**
> * wrappers for all the basic types (and derived types) of D
> * note: these wrappers are mutable
> */
> module dragon.math.basictypes;
> import dragon.math.numbers;
> import std.math;
> import std.string;
>
> /// wrapper for byte
> class Byte: numeric!(Byte){
> private byte value; /// value of instance
> public:
> this(byte b = 0){ value = b;} ///Constructor
> byte Value() {return value;} ///Returns: value of instance
> void Value(byte b) {value = b;} ///Params: b = new value
> byte opCast() {return value;} /// cast overload
> char[] toString() { return std.string.toString(value);}
> uint toHash() {return abs(value);}
>
> // binary operator TODO add documentation
> Byte opAdd(Byte b) { return new Byte(value + b.value);}
> Byte opAdd(byte b) { return new Byte(value + b);}
> Byte opSub(Byte b) { return new Byte(value - b.value);}
> Byte opSub(byte b) { return new Byte(value - b);}
> Byte opSub_r(byte b) { return new Byte(b - value);}
> Byte opMul(Byte b) { return new Byte(value * b.value);}
> Byte opMul(byte b) { return new Byte(value * b);}
> Byte opDiv(Byte b) { return new Byte(value / b.value);}
> Byte opDiv(byte b) { return new Byte(value / b);}
> Byte opDiv_r(byte b) {return new Byte(b / value);}
> Byte opMod(Byte b) {return new Byte(value % b.value);}
> Byte opMod(byte b) {return new Byte(value % b);}
> Byte opMod_r(byte b) { return new Byte(b % value);}
> Byte opAnd(Byte b) { return new Byte(value & b.value);}
> Byte opAnd(byte b) { return new Byte(value & b);}
> Byte opOr(Byte b) { return new Byte(value | b.value);}
> Byte opOr(byte b) { return new Byte(value | b);}
> Byte opXor(Byte b) { return new Byte(value ^ b.value);}
> Byte opXor(byte b) { return new Byte(value ^ b);}
> Byte opShl(int i) { return new Byte(value << i);}
> long opShl_r(long l) { return l << value;}
> Byte opShr(int i) {return new Byte(value >> i);}
> long opShr_r(long l) { return l >> value;}
> Byte opUShr(int i) {return new Byte(value >>> i);}
> long opUShr(long l) {return l >>> value;}
> //comparison operators
> int opEquals(Object o) {
> if(o is Byte) {
> Byte b = cast(Byte)o;
> return value == b.value;
> }
> return o == value;
> }
> int opEquals(long l) {
> return l = value;
> }
> int opCmp(Object o) {
> if(o is Byte) {
> Byte b = cast(Byte)o;
> if(value > b.value)return 1;
> if(value < b.value)return -1;
> return 0;
> }
> return o.opCmp(value);
> }
> int opCmp(long l) {
> if(value < l)return -1;
> if(value > l)return 1;
> return 0;
> }
> //assignment operators
> Byte opAssign(byte b) {
> value = b;
> return this;
> }
> Byte opAddAssign(Byte b) {
> value += b.value;
> return this;
> }
> Byte opAddAssign(byte b) {
> value += b;
> return this;
> }
> Byte opSubAssign(Byte b) {
> value -= b.value;
> return this;
> }
> Byte opSubAssign(byte b) {
> value -= b;
> return this;
> }
> Byte opMulAssign(Byte b) {
> value *= b.value;
> return this;
> }
> Byte opMulAssign(byte b) {
> value *= b;
> return this;
> }
> Byte opDivAssign(Byte b) {
> value /= b.value;
> return this;
> }
> Byte opDivAssign(byte b) {
> value /= b;
> return this;
> }
> Byte opModAssign(Byte b) {
> value %= b.value;
> return this;
> }
> Byte opModAssign(byte b) {
> value %= b;
> return this;
> }
> Byte opAndAssign(Byte b) {
> value &= b.value;
> return this;
> }
> Byte opAndAssign(byte b) {
> value &= b;
> return this;
> }
> Byte opOrAssign(Byte b) {
> value |= b.value;
> return this;
> }
> Byte opOrAssign(byte b) {
> value |= b;
> return this;
> }
> Byte opXorAssign(Byte b) {
> value ^= b.value;
> return this;
> }
> Byte opXorAssign(byte b) {
> value ^= b;
> return this;
> }
> Byte opShlAssign(Byte b) {
> value <<= b.value;
> return this;
> }
> Byte opShlAssign(byte b) {
> value <<= b;
> return this;
> }
> Byte opShrAssign(Byte b) {
> value >>= b.value;
> return this;
> }
> Byte opShrAssign(byte b) {
> value >>= b;
> return this;
> }
> Byte opUShrAssign(Byte b) {
> value >>>= b.value;
> return this;
> }
> Byte opUShrAssign(byte b) {
> value >>>= b;
> return this;
> }
>
> // unary operators TODO add documentation
> Byte opNeg() {return new Byte(-value);}
> Byte opPos() {return new Byte(+value);}
> Byte opCom() {return new Bye(~value);}
> Byte opPostInc() {
> scope temp = value;
> value++;
> return new Byte(temp);
> }
> Byte opPostDec() {
> scope temp = value;
> value--;
> return new Byte(temp);
> }
> }
>
> now the problem is a lack of implicit casting for user defined types the Byte cannot be implicitly cast to byte, int, long etc. even though such a cast would make sense. If implicit casting were allowed then a library could be fashioned with wrapper for all of the basic types and some less basic types such as cint, iint, fraction, radical, ifraction, cfraction, etc.
>
> my suggested syntax for overloading implicit casts is:
>
> implicit type1 cast(type2 var);
>
> where type1 is the type casting to and type2 is the type casting from
> this syntax would allow non-member functions to be used, so that implicit casts can be overloaded in specific contexts
> example:
> implicit int cast(long var){ return cast(int)var;}
> when you know that longs will never exceed the bound of ints
More information about the Digitalmars-d
mailing list