Graham St Jack Wrote:
> I have been trying (again) to start using const and immutable objects in
> a project, and found I kept getting stuck with the need to change the
> value of object references, which isn't allowed. I don't quite follow the
> arguments that mean that this has to be the case, but I'm prepared to
> accept them.
>
> After some experimenting with Andrei's Rebindable template, I still
> couldn't get past the problems. For a start, the get method is private so
> I couldn't test for null.
>
> In the end I cooked up the following, which is a very simple workaround
> that just lets me assign to a const or immutable object reference. It
> works just fine, and can be used in templates like containers without
> forcing the container to care about what it is containing.
>
> Comments?
>
> //
> // Assign dest to src, using brute-force methods as necessary if T
> // is an immutable or const object.
> //
> // The intent is to avoid needing routine nasty tricks in
> // application code, especially in template code which should be
> // spared the complication of handling this very annoying
> // restriction on objects. Use of this template function doesn't
> // let you change the object itself, just the reference to it - so
> // all should be well.
> //
> void forcefulAssign(T)(ref T dest, T src) {
> static if (!is(T X == const(U), U) && !is(T X == invariant(U), U)) {
> // T is not const or immutable - just assign normally
> dest = src;
> }
> else static if (is(T : Object)) {
> // T is a const or immutable object - use brute force
> U * ptr = cast(U *) &dest;
> *ptr = cast(U) src;
> }
> else {
> // T is some other const or immutable type - not assignable
> static assert(false, "cannot assign to " ~ T.stringof);
> }
> }
>
> // assign the default initializer to something
> void forcefulInitialize(T)(ref T dest) {
> static if (!is(T X == const(U), U) && !is(T X == invariant(U), U)) {
> // T is not const or immutable - just initialise normally
> dest = T.init;
> }
> else static if (is(T : Object)) {
> // T is a const or immutable object - use brute force
> U * ptr = cast(U *) &dest;
> *ptr = U.init;
> }
> else {
> // T is some other const or immutable type - not assignable
> static assert(false, "cannot assign to " ~ T.stringof);
> }
> }
>
I agree that D lacks a mechanism to separate the object from it's reference.
Maybe syntax like the following could be used to apply the storage class to the
object value, and not the reference value:
class Foo;
void bar(in Foo& foo) {}
It's quite ugly and C-like, but that's the first thing that came to mind. The
reference value is unique to the current method and shouldn't share the same
storage qualifiers as it's referenced memory.