How to break const

Christophe Travert travert at phare.normalesup.org
Tue Jun 19 10:40:22 PDT 2012


Christophe Travert, dans le message (digitalmars.D:170182), a écrit :
> Timon Gehr , dans le message (digitalmars.D:170178), a écrit :
>> That is completely unrelated.
>> It is impossible to justify transitivity of const for delegate context
>> pointers using this argument. It is far too general and the
>> justification for the general concept comes from a specific example
>> that is different from the one at hand.
>> 
>> The question is, what the meaning of 'const' references should be:
>> 
>> 1. data cannot be changed transitively through the reference
>> 
>> 2. the reference can reference both 'const' and 'immutable' data and
>>     'immutable' data can transitively not be changed through the
>>     reference.
>> 
>> 
>> 1. requires transitive const for delegate context pointers, 2. does not.
> 
> A const reference can contain
> 
> I don't understand the difference.

Apologies, I forgot to complete my post:

A const reference can contain both mutable and immutable data, as long 
as it does not allow to mutate it. I don't understand point 2: if the 
reference contain const reference, it should not modify the const 
reference. Of course, immutable data should not be changed in any case.

This is how I understand delegates should work:

[the rest of the post is unchanged]
> 
> struct Delegate(C, F, Args)
> {
>     C* ptr; // points to some structure containing all referenced data
>     R function(C*, Args) fun;
>     R opCall(Args) { return ptr.fun(Args); }
> }
> 
> The signature of opCall determines the type of the delegate. In reality, 
> the delegate is opaque, and C is not typed. ptr is a pointer to void*, 
> and fun knows how to use that pointer. But that does not prevent the 
> pointer to be const or immutable.
> 
> Note that calling opCall is not possible if the Delegate is const, or 
> part of a const structure, because opCall does not have the const 
> attribute.
> 
> But the signature of opCall could have any kind of attributes: const, 
> immutable, pure, nothrow, inout..., which can be reflected by the 
> delegates type.
> 
> A delegate of type "R delegate(Args) const" would be like this:
> 
> struct DelegateConst(C, R, Args...)
> {
>   const C* ptr;
>   R function(const C*, Args) fun;
>   R opCall(Args) const { return ptr.fun(Args); }
> }
> 
> Now it is possible to call opCall if the DelegateConst is const. 
> However, it is possible to build this delegate only if fun is const with 
> regard to its context argument.
> 
> The same holds if you replace const by immutable.
> 
> Now, the context pointer can point to all type of data. C is a like a 
> structure, and can contain any kind of data (mutable, const, immutable, 
> shared...). However transitivity rules must be preserved. If the data is 
> immutable, the delegate context pointer must be. If the data is a mix of 
> mutable, const, and immutable data, there is no problem, has long has 
> the function mutates only the mutable data (but then, the delegate's 
> frame pointer type must be mutable, and the delegate is not callable if 
> it is const).
> 
> However, it must respect transitivity: if the delegate is immutable, all 
> data contained in the context must be immutable. If the context pointer 
> is const, the data can be mutable, const, or immutable.
> 
> 
> And where does all this comes from ?
> delegates are primarily methods applied to a struct or class instance.
> 
> class S
> {
>   data d;
>   void method(arg);
> }
> 
> S s = new S;
> void delegate(arg) dg = &s.method;
> 
> The delegate is constructed directly from the object's method. (1)
> 
> That is why it must have the same signature has objects method. If you 
> want to fully represent methods, delegates must have all methods 
> attributes: pure, nothrow, (which is a problem to introduce in 
> toString methods, for example), etc... but also const, immutable, and 
> maybe one day inout.
> 
> Currently, delegates does not support all this. It makes life easier, 
> because we do not have a zillion types of delegates, and it gives a 
> little bit of air on const virality until we have proper systems to 
> simplify all this. But this is a gap in the langage. It is up to the 
> programmer to respect const transitivity, and not exploit this gap and 
> break the langage.
> 
> (1) In my first example, a langage delegate can be obtained from my 
> artificial Delegate template by taking the adresse of opApply:
> 
> Delegate!(C, R, Args) s;
> R delegate(Args) dg = &s.opApply
> 
> (2) Note that it is however possible to obtain a 'C delegate(Args) 
> const' but taking the adress of a const method.
> 
> class S
> {
>   data d;
>   void method(Arg) const;
> }
> 
> S s = new S;
> auto dg = &s.method; 
> 
> dg is infered as 'void delegate(Arg) const' by the compiler
> 
> -- 
> Christophe



More information about the Digitalmars-d mailing list