Alternative solutions to returning ref types.

Simen Kjaeraas simen.kjaras at gmail.com
Mon Mar 17 02:06:35 PDT 2008


On Sat, 15 Mar 2008 10:38:52 +0100, kede <dev at null.com> wrote:

> Hi...
>
> I'm still having a great time using D for graphics programming at the  
> moment.
> However, I'm constantly irritated by my initial design decision to  
> implement the lower level objects as structs simply because it has led  
> do (a now ridiculous amount) of code along the lines of the following:
>
> model.origin = model.origin + vec3(0,1,0);
>  -- or --
> o = model.origin;
> o.y += 1;
> model.orgin = o;
>
> When all I really want is just:   model.origin.y++;
> Worse still, model.origin.y++ is legal but doesn't do what you would  
> expect.
>
> I'm sure most of you have this problem to some degree or another.   
> However, it doesn't look like returnable ref types are going to be  
> implemented in D any time soon, so I want to ask you guys what you are  
> currently doing to deal with this.
>
> For the sake of discussion take a 3d vector object as an example.
> Given that it is small in size, frequently allocated and deallocated,  
> commonly used inside other class objects.
>
> The obvious solutions are:
> 1. Use a pointer to return it.  -- urgh
> 2. Implement it as a class.
> 3. As 2 with custom 'new' 'delete'
>
>
> Thanks in advance for any ideas you might have...
>
> Have fun,
> k


Just for the fun of it, I decided to try make a property struct, with  
overloaded operators. Any ideas for how to make this better are welcome.
Of course, this causes some overhead, but was a fun project, and if it  
helps anyone, I'm a happy cat.


Example usage:

class foo
{
private:
	int _a;
	float _b;
public:
	property!(int) a;
	property!(float) b;
	
	this()
	{
		a = &_a;
		b = &_b;
	}
}

-- Simen

-----------------------------------

struct property(T)
{
	T* data;
	
	T opNeg()
	{
		return -(*data);
	}
	
	T opPos()
	{
		return +(*data);
	}
	
	T opPostInc()
	{
		return (*data)++;
	}
	
	T opPostDec()
	{
		return (*data)--;
	}
	
	const
	{
	T opAdd(U)(U rhs)
	{
		return (*data) + rhs;
	}
	
	T opAdd_r(U)(U rhs)
	{
		return rhs + (*data);
	}
	
	T opSub(U)(U rhs)
	{
		return (*data) - rhs;
	}
	
	T opSub_r(U)(U rhs)
	{
		return rhs - (*data);
	}
	
	T opMul(U)(U rhs)
	{
		return (*data) * rhs;
	}
	
	T opMul_r(U)(U rhs)
	{
		return rhs * (*data);
	}
	
	T opDiv(U)(U rhs)
	{
		return (*data) / rhs;
	}
	
	T opDiv_r(U)(U rhs)
	{
		return rhs / (*data);
	}
	
	T opMod(U)(U rhs)
	{
		return (*data) % rhs;
	}
	
	T opMod_r(U)(U rhs)
	{
		return rhs % (*data);
	}
	
	T opAnd(U)(U rhs)
	{
		return (*data) & rhs;
	}
	
	T opAnd_r(U)(U rhs)
	{
		return rhs & (*data);
	}
	
	T opOr(U)(U rhs)
	{
		return (*data) | rhs;
	}
	
	T opOr(U)(U rhs)
	{
		return rhs | (*data);
	}
	
	T opXor(U)(U rhs)
	{
		return (*data) ^ rhs;
	}
	
	T opXor_r(U)(U rhs)
	{
		return rhs ^ (*data);
	}
	
	T opShl(U)(U rhs)
	{
		return (*data) << rhs;
	}
	
	T opShl_r(U)(U rhs)
	{
		return rhs << (*data);
	}
	
	T opShr(U)(U rhs)
	{
		return (*data) >> rhs;
	}
	
	T opShr_r(U)(U rhs)
	{
		return rhs >> (*data);
	}
	
	T opUShr(U)(U rhs)
	{
		return (*data) >>> rhs;
	}
	
	T opUShrs(U)(U rhs)
	{
		return rhs >>> (*data);
	}
	
	T opCat(U)(U rhs)
	{
		return (*data) ~ rhs;
	}
	
	T opCat_r(U)(U rhs)
	{
		return rhs ~ (*data);
	}
	
	}
	
	T opAssign(U)(U rhs)
	{
		static if (is (U : typeof(*this)))
		{
			data = rhs.data;
		}
		else static if (is(U : T*))
		{
			data = rhs;
		}
		else
		{
			(*data) = rhs;
		}
		return *data;
	}
	
	T opAddAssign(U)(U rhs)
	{
		*data += rhs;
		return *data;
	}
	
	T opSubAssign(U)(U rhs)
	{
		*data -= rhs;
		return *data;
	}
	
	T opMulAssign(U)(U rhs)
	{
		*data *= rhs;
		return *data;
	}
	
	T opDivAssign(U)(U rhs)
	{
		*data /= rhs;
		return *data;
	}
	
	T opModAssign(U)(U rhs)
	{
		*data %= rhs;
		return *data;
	}
	
	T opAndAssign(U)(U rhs)
	{
		*data &= rhs;
		return *data;
	}
	
	T opOrAssign(U)(U rhs)
	{
		*data |= rhs;
		return *data;
	}
	
	T opXorAssign(U)(U rhs)
	{
		*data ^= rhs;
		return *data;
	}
	
	T opShlAssign(U)(U rhs)
	{
		*data <<= rhs;
		return *data;
	}
	
	T opShrAssign(U)(U rhs)
	{
		*data >>= rhs;
		return *data;
	}
	
	T opUShrAssign(U)(U rhs)
	{
		*data >>>= rhs;
		return *data;
	}
}

property!(T) Property(T)(T* _data)
{
	property!(T) tmp;
	tmp.data = _data;
	return tmp;
}



More information about the Digitalmars-d mailing list