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