Suggestion: class/struct tuples preserve anonymous unions/structs

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Thu Feb 15 02:23:40 PST 2007


Jarrett Billingsley wrote:
> The anonymous union is getting "flattened out" by the type tuple mechanism.
> 
> This messes up some automation features.  For example I'm trying to write a 
> simple "Serialize" function which can serialize entire structs.  But unions 
> can't be automatically serialized, since the Serialize function has no idea 
> which member of the union is currently "valid."  So I have error checking to 
> disallow serializing unions, but since the .tupleof facility flattens out 
> anonymous unions, it can't check for errors (and therefore I don't know that 
> there's a problem until I write the struct out to a file and end up with a 
> bunch of invalid members, since they came from the anonymous union).
> 
> I'm not sure how anonymous unions and structs are handled by the compiler. 
> If they are created as "secret" types, would it then be possible for the 
> above struct with the anonymous union to consist of:
> 
> int
> test.S.__UNION0
> 
> or something like that? 

I don't think it's being "flattened out" by the type tuple mechanism, I 
think it happens *before* that. They're not created as secret types, 
they just seem to use different rules for offset calculation.
I'm not really sure whether or not this is a bug in the compiler, but it 
happens.

The following template can be used to check for unions (anonymous and 
named) and generate compile errors when it finds any:
-----
/** static asserts when T is a union or contains unions.
  *  Note: the 'Idx' parameter should be left at the default by
  *        code outside the template.
  */
template validate(T, size_t Idx = 0) {
     static assert(!is(T == union), T.stringof ~ " is a union itself!");
     static assert(!is(typeof(T.tupleof)[Idx] == union),
         "Member " ~ Idx.stringof ~ " of " ~ T.stringof ~ " is a union");

     static if (Idx + 1 < T.tupleof.length) {
         // check overlap caused by anonymous union members
         static assert(T.tupleof[Idx].offsetof + T.tupleof[Idx].sizeof 
<= T.tupleof[Idx + 1].offsetof,
             "Member " ~ Idx.stringof ~ " of " ~ T.stringof ~ " overlaps 
the next member");
         // and check the other members
         mixin validate!(T, Idx + 1);
     }

     static if (Idx < T.tupleof.length) {
         // Recurse into member structs
         static if (is(typeof(T.tupleof)[Idx] == struct))
             mixin validate!(typeof(T.tupleof)[Idx]);

         // uncomment these lines to recurse into member class 
references as well:
         //else static if (is(typeof(T.tupleof)[Idx] == class))
         //    mixin validate!(typeof(T.tupleof)[Idx]);
     }
}


//
// Some test code:
//

struct SAnonUnion
{
     int x;

     union
     {
         int a;
         int b;
     }
}
struct SUnion
{
     int x;

     union U
     {
         int a;
         int b;
     }
     U u;
}

struct SValid
{
     int x;

     int a;
     int b;
}

class Class { SUnion u; }

struct SNested
{
     Class u;
}

void main()
{
     //mixin validate!(SAnonUnion);    // error :)
     //mixin validate!(SUnion);        // error :)
     mixin validate!(SNested);       // error if class references are 
followed, or 'Class' is changed to a struct
     mixin validate!(SValid);
}
-----
(You may have to correct some line wrapping before it'll compile)



More information about the Digitalmars-d mailing list