typedefs are useless

Simen Kjaeraas simen.kjaras at NOSPAM.gmail.com
Tue Dec 4 09:53:49 PST 2007


Steven Schveighoffer Wrote:
> FWIW, you can do stuff like this today by using a struct with a single 
> member of the base type you want, but you must define all the operators, but 
> there is no implicit cast back to the base type.  A struct is POD, so it 
> occupies the same space as the single member, so you get no loss of 
> efficiency there.
> 
> The other problem is that operators can't be used in constant expressions 
> (which is another pet peeve I have about this).  Using a typedef would allow 
> operators to be used.
> 
> I want to say I really like BCS's idea as it really allows you to redefine 
> all aspects of a typedef.  This would be perfect for what I am trying to do.
> 
> -Steve 

On Tue, 04 Dec 2007 15:38:40 +0100, Steven Schveighoffer <schveiguy at yahoo.com> wrote:
> FWIW, you can do stuff like this today by using a struct with a single
> member of the base type you want, but you must define all the operators,  
> but
> there is no implicit cast back to the base type.  A struct is POD, so it
> occupies the same space as the single member, so you get no loss of
> efficiency there.
>
> The other problem is that operators can't be used in constant expressions
> (which is another pet peeve I have about this).  Using a typedef would  
> allow
> operators to be used.
>
> I want to say I really like BCS's idea as it really allows you to  
> redefine
> all aspects of a typedef.  This would be perfect for what I am trying to  
> do.
>
> -Steve

Have a template, it's on the house.

// start code
template TypeDef(T)
{
	T value;
	
	typeof(this) opNeg()
	{
		typeof(this) tmp;
		tmp.value = -this.value;
		return tmp;
	}
	
	typeof(this) opPostInc()
	{
		typeof(this) tmp;
		tmp.value = value++;
		return tmp;
	}
	
	typeof(this) opPostDec()
	{
		typeof(this) tmp;
		tmp.value = value--;
		return tmp;
	}
	
	T opCast()
	{
		return value;
	}
	
	static typeof(this) opCall(T rhs)
	{
		typeof(this) tmp;
		tmp.value = rhs;
		return tmp;
	}
	
	T opCall() // ugly hack to simulate implicit cast
	{
		return value;
	}
	
	typeof(this) opAdd(T rhs)
	{
		typeof(this) tmp;
		tmp.value = value + rhs;
		return tmp;
	}
	
	typeof(this) opSub(T rhs)
	{
		typeof(this) tmp;
		tmp.value = value + rhs;
		return tmp;
	}
	
	typeof(this) opMul(T rhs)
	{
		typeof(this) tmp;
		tmp.value = value * rhs;
		return tmp;
	}
	
	typeof(this) opDiv(T rhs)
	{
		typeof(this) tmp;
		tmp.value = value / rhs;
		return tmp;
	}
	
	typeof(this) opMod(T rhs)
	{
		typeof(this) tmp;
		tmp.value = value % rhs;
		return tmp;
	}
	
	typeof(this) opAssign(T rhs)
	{
		value = rhs;
		return this;
	}
	
	typeof(this) opAddAssign(T rhs)
	{
		value += rhs;
		return this;
	}
	
	typeof(this) opSubAssign(T rhs)
	{
		value -= rhs;
		return this;
	}
	
	typeof(this) opMulAssign(T rhs)
	{
		value *= rhs;
		return this;
	}
	
	typeof(this) opDivAssign(T rhs)
	{
		value /= rhs;
		return this;
	}
	
	typeof(this) opModAssign(T rhs)
	{
		value %= rhs;
		return this;
	}
	
	
	
	
	typeof(this) opAdd(typeof(this) rhs)
	{
		typeof(this) tmp;
		tmp.value = value + rhs.value;
		return tmp;
	}
	
	typeof(this) opSub(typeof(this) rhs)
	{
		typeof(this) tmp;
		tmp.value = value + rhs.value;
		return tmp;
	}
	
	typeof(this) opMul(typeof(this) rhs)
	{
		typeof(this) tmp;
		tmp.value = value * rhs.value;
		return tmp;
	}
	
	typeof(this) opDiv(typeof(this) rhs)
	{
		typeof(this) tmp;
		tmp.value = value / rhs.value;
		return tmp;
	}
	
	typeof(this) opMod(typeof(this) rhs)
	{
		typeof(this) tmp;
		tmp.value = value % rhs.value;
		return tmp;
	}
	
	typeof(this) opAddAssign(typeof(this) rhs)
	{
		value += rhs.value;
		return this;
	}
	
	typeof(this) opSubAssign(typeof(this) rhs)
	{
		value -= rhs.value;
		return this;
	}
	
	typeof(this) opMulAssign(typeof(this) rhs)
	{
		value *= rhs.value;
		return this;
	}
	
	typeof(this) opDivAssign(typeof(this) rhs)
	{
		value /= rhs.value;
		return this;
	}
	
	typeof(this) opModAssign(typeof(this) rhs)
	{
		value %= rhs.value;
		return this;
	}
	
	string toString()
	{
		return std.stdio.toString(value);
	}
}
// end code

Used it for a quick 'n dirty test like this:

// start code
struct ImaginaryNumber
{
	mixin TypeDef!(int);
	
	typeof(this) opAddAssign(int rhs){return this;}
	typeof(this) opSubAssign(int rhs){return this;}
	
	int opMulAssign(typeof(*this) rhs)
	{
		int result = value * rhs.value;
		value = 0;
		return -result;
	}
	
	typeof(this) opMulAssign(int rhs)
	{
		value *= rhs;
		return this;
	}
	
	int opMul(typeof(*this) rhs)
	{
		return -value * rhs.value;
	}
	
	typeof(this) opMul(int rhs)
	{
		typeof(this) tmp;
		tmp.value = value * rhs;
		return tmp;
	}
}
// end code

I'd like to have a T opImplicitCastTo() {return value;} in there as well, but that will have to wait.




More information about the Digitalmars-d mailing list