On 07/13/2016 07:01 AM, Adam D. Ruppe wrote:
> On Wednesday, 13 July 2016 at 12:28:57 UTC, zodd wrote:
>> This code works as I expected but I'm unsure that it's correct.
>
> Yes, your code is legal.
>
> What isn't legal is using some type that isn't there at runtime, like
>
> union A {
>     int[] a;
>     char[] b;
> }
>
> A u;
>
> u.a = [1,2];
>
> u.b.length
>
>
> The compiler will let you do it, but being a union, it will show length
> == 1 because it was set to an int[], but that's not really correct for a
> char[].
>
>
> But the way you did it, initializing to the proper type before accessing
> it, is allowed.

Although, in some cases even that assignment operation can do the wrong thing. In general, the left-hand side of the assignment does not hold the invariants of that user-defined type:

import std.stdio;

struct S {
    string fileName;

    S opAssign(S) const {
        writefln("deleting %s", fileName);    // <-- Oops.
        return this;
    }
}

union U {
    S s;
    string file;
}

void main() {
    U u;
    u.file = "important_file.txt";

    // This assignment is executed on an S that is not properly
    // initialized. The operation deletes an unrelated file.
    u.s = S.init;
}


Of course, users of unions must understand how bits of different types are shared and how that can cause trouble.

Ali

Reply via email to