I just thought of an interesting way to make a logical const object without casts. It requires a little extra storage, but works without changes to the current compiler (and requires no casts).

Here's the code, then I'll talk about the implications:

import std.stdio;

class D
{
    D getme() { return this;}
    void foo() {writeln("mutable!");}
}

class C
{
    D delegate() d;
    this()
    {
      auto dinst = new D;
      this.d = &dinst.getme;
    }
    void bar() const { d().foo();}
}

void main()
{
    auto c = new C;
    c.bar();
}

outputs:

mutable!

So how does it work? It works because delegates and especially the delegate data is *not* affected by const. So even when C is temporarily cast to const, the delegate is not affected (i.e. it's context pointer is not temporarily cast to const).

Doesn't this poke holes in const? Of course it does, but no more holes than are present via another logical const scheme (i.e. using a globally stored AA to retrieve the data).

Why is this better than simply casting away const?

First, because simply casting away const and modifying the data is undefined, I don't think the method I created results in undefined behavior. Second, because compiler is still fully enforcing const/immutable. For example, you could not assign d to &dinst.getme if dinst is const or immutable, and once inside a const function, I cannot change the delegate, I can only call it. Third, because the D instance *doesn't actually live* in the C object. You can see, I *never* assigned a D instance to a member variable of C, I only assigned the delegate. The D instance lives on the heap (and technically can be passed in via the constructor if need be).

The only drawbacks here are, we have to needlessly store the delegate function pointer (assuming we are always going to use &getme), and the delegate cannot be inlined.

I'm actually thinking that very controlled patterns of logical const like this could be implemented via mixin, and be sanctioned by the library. The way this pattern works, you can dictate as the author of a class whether that class can be a logically const part of another object or not, simply by choosing to implement getme or not.

What do people think about this?

-Steve

Reply via email to