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.