Top 4 use cases for mutable references to const data

Robert Fraser fraserofthenight at gmail.com
Tue Sep 11 13:41:38 PDT 2007


I posted some of this in the other thread, but I think it deserves a thread of its own. The problem is this: under the new const regime, it sounds like it will be impossible to declare tail-const class references without head-constness too. Walter's argument against this is that he can't think of a use case when one would want a non-const reference to const data. I, on the other hand, really think that's the whole _point_ of constness. I usually write methods short enough to never need head-const (sadly, my colleagues don't always agree), so rarely use the concept at all. The idea of a reference to constant data, though, is what make const useful to me in the first place, since one can pass a const reference to another component and know that component isn't messing with it.

So, here's my top 4 (actually the first 4 of many, many, many that came to my mind, but 4 that are much more difficult to do without mutable references) of having mutable references to const data. Without this, const is simply unusable for me, and I'm sure others will agree. Basically any case where one would want a mutable reference is a use-case for possible constness, since to be able to mutate that reference under the new regime, you would needed to cast away the constness (thus removing its usefulness). This gets especially hairy in the case of invariant.

Example 1: Member variables:
----------------------------------------
The following would be ILLEGAL without mutable references to const data:

class Foo { }
class Bar
{
    const(Foo) foo;
    this(const(Foo) foo)
    {
        this.foo = foo;
    }
}

This would be somewhat possible with structs (using struct literals, struct initializers, etc.)

Example 2: Iteration through a linked list of classes
----------------------------------------------------------------------
The following would be ILLEGAL without mutable references to const data:

class Node
{
    Node next;
    int data;
}

const(Node) search(const(Node) first, int value)
{
    const(Node) current = first;
    do
    {
        if(current is null)
            return null;
        if(current.data == value)
            return current;
        current = current.next;
    }
}

If you ask why a linked list of classes and not structs (to which mutable pointers to const data would be possible), remember that linked lists aren't always a general list of elements, thy could be a filter chain or a user-subclassable list of timer events as used in SEDA, or anything else tow which polymorphism applies. If you want to say "composition is a better design descision here than polymorphism," I hear ya, but we shouldn't be forced to change entiore design patterns to support constness, and taht this applies to basically all sorts of iteration (possibly even returning a class reference with an opApply).

Example 3: Caches
--------------------------
This is too complex an example to simmer down to a 5-10 line example, but imagine a caching function (class, struct). You wouldn't want your cache function changing the data you pass in, so you want to mark that data const. However, the cache only keeps a limited set of references to the data (perhaps the most frequently accessed, or most recently accessed, or everything until memory starts getting low, where it starts discarding). To keep this cache, you'd need mutable references (after all, the data that's currently cached is changing), but the cache never changes the data, so these references should be tail-const. Again, impossible.

Example 4: Associative Arrays:
-----------------------------------------
The following would be ILLEGAL without mutable references to const data:

class Person { }
const(Person)[string] people;

//...

const(Person) awesomePerson = "Robert" in people;
if(null is awesomePerson)
{
    awesomePerson = new Person();
    people["Robert"] = awesomePerson;
}
// Do stuff with awesomePerson

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

I could go on for a while, but most of the other cases I can think of are more coding style things that could be worked around with temporary variables, etc. And, of course, all this stuff can be worked around with casting. However, that defeats the purpose of constness entirely, IMO.

PS My spell checker's suggestions for "constness": moistness's, moistness, moistnesses, colorfastness, robustness



More information about the Digitalmars-d mailing list