www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - built-in types inside of a union

reply zodd <zodd maill.com> writes:
Can I place a dynamic array, an associative array and a string to 
a union and work with all elements? They are built-in types, but 
actually not primitive ones (this is not allowed in C++ for 
example). That's why I'm in doubt. I'm trying to implement 
something close to variant type (with a few restricted underlying 
types) for education purposes.

union Foo {
     int[] array;
     int[string] map;
     string str;
}

Foo u;

u.array = [];
u.array ~= 20;
u.array ~= 31;
writeln(u.array);

u.map = (int[string]).init;
u.map["test"] = 20;
u.map["value"] = 31;
writeln(u.map);

u.str = "test";
writeln(u.str);

This code works as I expected but I'm unsure that it's correct.
Jul 13 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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.
Jul 13 2016
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Jul 13 2016
prev sibling parent zodd <zodd maill.com> writes:
On Wednesday, 13 July 2016 at 14:01:25 UTC, Adam D. Ruppe wrote:
 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.
Thank you!
Jul 13 2016