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