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.

Reply via email to