logical const without casts!

Christophe travert at phare.normalesup.org
Fri Sep 30 06:27:31 PDT 2011


"Steven Schveighoffer" , dans le message (digitalmars.D:145767), a
 écrit :
> On Thu, 29 Sep 2011 13:26:11 -0400, Steven Schveighoffer  
> <schveiguy at yahoo.com> wrote:
> 
>> On Thu, 29 Sep 2011 13:06:55 -0400, Simen Kjaeraas  
>> <simen.kjaras at gmail.com> wrote:
>>
>>> On Thu, 29 Sep 2011 16:54:24 +0200, Steven Schveighoffer  
>>> <schveiguy at yahoo.com> wrote:
>>>
>>>> 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).
>>> [snip]
>>>> What do people think about this?
>>>
>>> This is what I think about it:
>>>
>>
>> I agree this breaks immutability, and needs to be addressed.  I think  
>> probably implicit casting of delegates (or items that containe  
>> delegates) to immutable from strong-pure functions should be disallowed.
>>
>> But it's not the pattern I described, and uses a relatively new trick  
>> (implicit immutable casting).  I'll file a bug for this case.
>>
> 
> http://d.puremagic.com/issues/show_bug.cgi?id=6741


Well, if the langage wants to be consistent, you should prevent implicit 
casting of delegates to const, not just to immutable.

What you revealed is very interesting, but it is clearly a bug. A 
delegate context pointer in a const object should be const, and the 
delegate function should be const with regard to its context pointer if 
you want the function to be called when the delegate is const. 
Constness has to apply to delegates just like it applies to structs. The 
explanation gets messy. An example:


This is what the compiler should say:
>>> class A {
>>>      int n;
>>>      void delegate( ) dg;
>>> }
>>>
>>> pure
>>> A createAnA( int n ) {
>>>      A result = new A;
>>>      result.n = n;
>>>      result.dg = (){ result.n++; };
>>>      return result;
>>> }
>>>
>>> void main( ) {
>>>      immutable A tmp = createAnA( 3 );
>>>      assert( tmp.n == 3 );
>>>      tmp.dg();
^error: cannot call non const delegate A.dg from an immutable object.
>>>      assert( tmp.n == 3 );
>>> }

An this is the fix:
>>> class A {
>>>      int n;
      void delegate( ) const dg; // or const(void delegate()) dg;
>>> }
>>>
>>> pure
>>> A createAnA( int n ) {
>>>      A result = new A;
>>>      result.n = n;
      // result.dg = (){ result.n++; }; would result in:
      // error: non const (unamed) delegate cannot be assigned to 
      // const delegate A.dg.
      result.dg = (){ result.n+1; }; // this one is fine.
>>>      return result;
>>> }
>>>
>>> void main( ) {
>>>      immutable A tmp = createAnA( 3 );
>>>      assert( tmp.n == 3 );
         tmp.dg(); // OK, A.dg is const so it can be called
>>>      assert( tmp.n == 3 );
>>> }


I guess you could also hide a mutable pointer of an immutable object 
during its construction with the same trick.

-- 
Christophe


More information about the Digitalmars-d mailing list