On 2009-12-17 23:38:58 -0500, Graham St Jack <[email protected]> said:

Immutable or const objects are a real pain because I can't have a mutable
reference to them. Rebindable doesn't seem to work, and I haven't been
able to make a version that works well enough.

In my observation, just like the most useful string type is defined as immutable(char)[] and thus is rebindable, most of the immutable objects I need also need to be rebindable. Rebindable being the most needed case, it means that I almost always need to write Rebindable!(immutable Object) for my immutable or const objects, which is a pain.

I've been wondering yesterday if being rebindable shouldn't just be the default for objects. The rule would be that reference types are rebindable unless marked with final. So you would have:

        const(Object)           o1; // rebindable
        const(final Object)     o2; // not rebindable
        immutable(Object)       o3; // rebindable
        immutable(final Object) o4; // not rebindable

Final would have no effect on non-reference types (anything but classes and interfaces). I can see how it isn't necessarily coherent with the rest of the const system for value types, but reference types are different from value types too.

In essence, I just want the most frequently used type (a rebindable object) to be easier to write than Rebindable!(immutable Object), so I'm open to other ideas too.

As for a Rebindable that works, I've made one. Unfortunately, use of alias this is broken because of this bug <http://d.puremagic.com/issues/show_bug.cgi?id=3626>, so for now you need to always use the "get" parameter for comparing to null and other things that don't start with a dot.


private template Rebindable(T) if (is(T == class) || isArray!(T))
{
   static if (!is(T X == const(U), U) && !is(T X == immutable(U), U))
   {
       alias T Rebindable;
   }
   else static if (isArray!(T))
   {
       alias const(ElementType!(T))[] Rebindable;
   }
   else
   {
       struct Rebindable
       {
                        private U stripped;
                        
           void opAssign(T another)
           {
               stripped = cast(U) another;
           }
                        this(T value) {
                                this = value;
                        }
           T get() const {
                                return cast(T)stripped;
                        }
                        T opDot() const {
                                return get;
                        }
       }
   }
}

--
Michel Fortin
[email protected]
http://michelf.com/

Reply via email to