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