Thread overview
Re: Why doesn't alias this work with arrays?
Jun 18, 2012
Jonathan M Davis
Jun 18, 2012
Andrej Mitrovic
Jun 18, 2012
Jonathan M Davis
June 18, 2012
On Monday, June 18, 2012 18:51:01 Andrej Mitrovic wrote:
> struct Wrap
> {
> string wrap;
> alias wrap this;
> }
> 
> void main()
> {
> Wrap x;
> x = "foo"; // ok
> Wrap[] y = ["foo", "bar"]; // fail
> }
> 
> Error: cannot implicitly convert expression (["foo","bar"]) of type
> string[] to Wrap[]
> 
> Any special reason why this doesn't work? I hope it's just a bug or unfinished implementation.

Generally, the type of the right-hand side of an assignment is determined independently of the left-hand side. So, the type of ["foo", "bar"] would be determined to be string[] before the compiler did anything with the left-hand side. At that point, you'd need to be converting from string[] to Wrap[], which would mean creating a new array, which isn't the sort of thing that happens implicitly.

Now, there are a few exceptions.

ubyte[] a = [1, 2, 3, 4];

works even though [1, 2, 3, 4] is normally typed as int[], so the compiler does adjust the type of the right-hand side under some circumstances, but it's not the normal thing to do, which is probably why it's not working for you.

- Jonathan M Davis
June 18, 2012
On 6/18/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> At that point, you'd need to be converting from string[] to Wrap[], which would mean creating a new array

It doesn't have to allocate anything because there's the 'alias this' and a single data member. All the compiler has to do is cast the array type to Wrap[]. Casting is safe in this case and should be allowed to be implicit:

void main()
{
    string[] x = ["foo", "bar"];
    Wrap[] y = cast(Wrap[])x;
    assert(y[0] == "foo");  // safe
}

Of course this only works if there are no other data fields in Wrap except the string, and that's exactly what I have in this case.
June 18, 2012
On Monday, June 18, 2012 19:05:35 Andrej Mitrovic wrote:
> On 6/18/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> > At that point, you'd need to be converting from string[] to Wrap[], which would mean creating a new array
> 
> It doesn't have to allocate anything because there's the 'alias this' and a single data member. All the compiler has to do is cast the array type to Wrap[]. Casting is safe in this case and should be allowed to be implicit:
> 
> void main()
> {
> string[] x = ["foo", "bar"];
> Wrap[] y = cast(Wrap[])x;
> assert(y[0] == "foo"); // safe
> }
> 
> Of course this only works if there are no other data fields in Wrap except the string, and that's exactly what I have in this case.

Yes, but you never defined such a conversion. With alias this, you told the compiler that when you need to convert a Wrap to a string or a string to Wrap, it should use the wrap member variable as if it were the object. You can't even construct a Wrap from a string. You didn't tell the compiler how. Note that

Wrap w = "hello";

doesn't compile. The fact that Wrap doesn't happen to have any other member variable is irrelevant. The only conversion that the compiler knows about is the alias this, and that doesn't take into account the rest of the struct at all.

- Jonathan M Davis