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