logical const without casts!

Steven Schveighoffer schveiguy at yahoo.com
Thu Sep 29 07:54:24 PDT 2011


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


More information about the Digitalmars-d mailing list