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