alias this doesn't work for properties.

JS js.mdnq at gmail.com
Thu Aug 1 17:36:18 PDT 2013


On Thursday, 1 August 2013 at 23:51:38 UTC, John Colvin wrote:
> On Thursday, 1 August 2013 at 22:23:40 UTC, JS wrote:
>> This is wrong because
>>
>> (cast(A)b.Y) = 3;
>>
>> works.
>
> That's an interesting case. cast(A)b.Y) is using the B getter 
> property, which makes sense as, due to the cast, nothing in B 
> can be called for the assigment.
>
> So you have (in psuedo-code, all properties expanded as 
> getY/setY):
>     b.getY.castToA = 3;
> wheras the previous example is:
>     b.setY(3);
>
> Neither are an int being implicitly converted to an A
>
>
>> b.Y = 3 should do the same as b.a = 3 which should be the same 
>> as b.a.x = 3.
>
> Why that can't work:
>
> struct A
> {
>     double x;
>     alias x this;
> }
> struct B
> {
>     private A a;
>     @property A Y() { importantGetPrep(); return a; }
>     @property void Y(A v) { importantSetPrep(); a = v; }
> }
> void main()
> {
>     B b;
>     b.Y = 3;  //cannot be a call to the setter as cannot 
> convert 3 to A .
>               //cannot be a call to the getter followed by an 
> assigment
>               //as the assignment would then have no effect on 
> b.a
>               //due to value semantics.
>               //cannot be anything else as it would bypass the
>               //important*etPrep that must be called on all 
> accesses
>               //to B.a .
> }
>
> Putting functions like important*etPrep in properties are one 
> of the main reasons why properties are useful, it would be a 
> very bad idea to let them be circumvented by an implementation 
> change in an internal struct.

Ok, I don't know why you keep saying 3 cannot be "converted" to 
A. Do you

Realize that the ultimate goal is to assign 3 to x? 3 is an int 
and x is a double, there is no conversion issues here.


if I do a = 3; b.Y = a; then it is no problem.

The issue is that b.Y wants an A and ignores the alias, I think 
this is wrong behavior because when you alias A it is suppose to 
act like that type... in this case it doesn't. Simple as that.

I can see why in some cases it is suppose to act the way it does, 
e.g., what if B.Y uses other fields of A, you obviously can't use 
a int then. If this is the case a run time error or compile time 
error should occur.

In any case, I'll just overload the setter to accept double and 
be done with it. Arguing whether it is a flaw/limitation in D or 
a flaw/limitation in my thinking won't get the behavior I want.

Note, I can just use a setter on double then it will work fine. 
This is not the behavior I want though because I breaks the 
homogeneity of my code generation.

IMO, if the argument to a setter has an alias this, that type 
should also work for the argument. If the body of the setter uses 
things not in the aliased type then it it should be an error(in 
that case, you should overload the setter).

This way you get the logical behavior expected but can also 
handle the more complex case.

code:

struct A { value double; int x; alias this value; }

class B {

@property A prop(A v)
{
    A a = new A;
    a.value = a.x;  // error if v is double and no setter for 
double, remove line to make it work.
    return a;
}

//@property A prop(double v) { ... } // specialize to prevent 
error for doubles


This way for simple properties one gets the expected behavior for 
alias this.



More information about the Digitalmars-d mailing list