logical const without casts!

Steven Schveighoffer schveiguy at yahoo.com
Fri Sep 30 11:07:54 PDT 2011


On Fri, 30 Sep 2011 14:00:36 -0400, Michel Fortin  
<michel.fortin at michelf.com> wrote:

> On 2011-09-30 17:46:13 +0000, "Steven Schveighoffer"  
> <schveiguy at yahoo.com> said:
>
>> On Fri, 30 Sep 2011 13:38:31 -0400, Michel Fortin   
>> <michel.fortin at michelf.com> wrote:
>>
>>> On 2011-09-29 14:54:24 +0000, "Steven Schveighoffer"   
>>> <schveiguy at yahoo.com> said:
>>>
>>>> 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).
>>>  This is a hole in the transitive const, because the delegate contains  
>>> a  pointer to mutable data. It also is a potential source of of low  
>>> level  races since returning that type from a pure function could make  
>>> it  immutable, which can then make this mutable data accessible to  
>>> multiple  threads with no synchronization or atomics to protect the  
>>> data's  integrity.
>>  Simen Kjaeraas and Christophe brought up the same points.  I filed a  
>> bug  on it:
>>  http://d.puremagic.com/issues/show_bug.cgi?id=6741
>
> Interesting proposal. You realize if we had a true 'mutable' storage  
> class for class members it could obey the same rule as you propose in  
> that bug report: it should be illegal to cast a mutable-containing  
> object or struct to immutable implicitly. An explicit cast should be  
> required.

Yes, but the benefit of the proposal is -- it already works in the current  
compiler :)  You have a monstrous hill to climb to convince Walter to  
*add* mutable storage class, but we don't even have to ask for this one,  
it works today.

> Also, if we had shared delegates -- delegates which are guarantied to  
> only manipulate shared data -- we could allow the class that contains a  
> shared delegate to be implicitly converted to immutable.

I'd like to avoid the complication of having any attributes that apply to  
the context pointer.  I like how delegates just fit in anywhere, no matter  
what the context pointer type is (or its constancy).

-Steve


More information about the Digitalmars-d mailing list