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