How to break const

Artur Skawina art.08.09 at gmail.com
Mon Jun 18 07:28:02 PDT 2012


On 06/18/12 14:45, deadalnix wrote:
> Le 18/06/2012 07:59, Matthias Walter a écrit :
>> On 06/18/2012 07:36 AM, Mehrdad wrote:
>>> Is it just me, or did I subvert the type system here?
>>>
>>>
>>> import std.stdio;
>>>
>>> struct Const
>>> {
>>>      this(void delegate() increment)
>>>      { this.increment = increment; }
>>>      int a;
>>>      void delegate() increment;
>>>      void oops() const { this.increment(); }
>>> }
>>>
>>> void main()
>>> {
>>>      Const c;
>>>      c = Const({ c.a++; });
>>>      writeln(c.a);
>>>      c.oops();
>>>      writeln(c.a);
>>> }
>>>
>>
>> I don't think so. When calling oops you have two references to the object c:
>>
>> - The this-pointer of the object itself which is not allowed to change
>> the object in the const-call.
>> - The reference from within main which is allowed to change it and can
>> be reached via the frame pointer of the delegate.
>>
>> I see this as perfectly valid code. Of course, opinions may differ here.
>>
>> Matthias
> 
> The hidden parameter of the delegate is stored in c. This hidden parameter must be qualified with const when c is made const, for transitivity. However, it isn't.
> 
> In short :
> - c is made const
> - the frame pointer is stored in c
> - the frame pointer must be made const for transitivity.
> 
> => The type system is broken. You'll find many examples of this behavior with delegates.

It's fine, if you view a delegate as opaque.

'this' being const does not preclude accessing the object that 'this'
points to via another, mutable, reference.

Consider the alternative - you'd have to forbid storing any delegate
with a non-const non-value argument inside any object.

And "breaking" const would then _still_ be possible and trivial.

   import std.stdio;

   S*[const(S)*] g;

   struct S {
      int i;
      this(int i) { this.i = i; g[&this] = &this; }
      void f() const { g[&this].i=666; }
   }

   void main() {
      const s = S(42);
      writeln(s);
      s.f();
      writeln(s);
   }

Yes, D's "pure" could help here, only it's misnamed (even if in
this particular case that term would be fitting).

artur


More information about the Digitalmars-d mailing list