Why are these restriction to union

Started by
7 comments, last by Jan Wassenberg 14 years, 7 months ago
please explain with examples why these restriction are there in union 1.No static variables can be members of a union. 2.A reference member cannot be used 3.A union cannot have as a member any object that overloads the = operator 4.no object can be a member of a union if the object has an explicit constructor or destructor function. 5.unions cannot be involved in inheritance
Advertisement
We don't typically like answering homework questions here.

Having said that, unions only really make sense with PODs anyway. Everything else stems from that.
Dura lex sed lex.

Codeka: C++0x has unrestricted unions: n2544.pdf (this might also be useful for the OP's homework). In the end, pod or non-pod, everything is bits and bytes (or let's concentrate on the byte, which is the smallest common denominator in C++), and unions are anyways not for everyday use and for careful programmers only, so restrictions towards POD-types always seemed unnatural to me (imho, it doesn't make less sense than with restricted unions).
Quote:Original post by phresnel
Codeka: C++0x has unrestricted unions: n2544.pdf
Hmm, didn't know that. Personally, I think they should stay the way they are - that proposal looks like pretty scary to me - but I'm not a language designer :-)
They could be really useful e.g. to write variants of non-pod types, which is something I could really need. And imagine how nice you could define a generic variant type using variadic templates, yay. Also note that with the relaxation of POD rules, some more types considered non-POD so far will now qualify as a POD.

Hmmm, minds of more flexible bitwise-memcpy come to mind ... all that in combination with better traits (is_pod<T> anyone?).
Quote:Original post by Codeka
Hmm, didn't know that. Personally, I think they should stay the way they are - that proposal looks like pretty scary to me - but I'm not a language designer :-)


Personally I wonder what unions are good for anyway. :p I've never ever felt the need to use a union anywhere.



Quote:Original post by Red Ant
Quote:Original post by Codeka
Hmm, didn't know that. Personally, I think they should stay the way they are - that proposal looks like pretty scary to me - but I'm not a language designer :-)


Personally I wonder what unions are good for anyway. :p I've never ever felt the need to use a union anywhere.


There are 4 basic uses of unions I'm aware of.

1) When you need to keep a class size small to optimize cache coherency, you may find that two data members are only used in a mutually exclusive context. In this case using a union provides a simple and intuitive syntax for accessing these two separate variables without bloating the class, and without the need for ugly bit hacks.

2) They are sometimes used essentially as a replacement reinterpret_cast, although I believe this may technically be bad behavior.

3) They provide a convenient syntax for accessing the same variable by two different names, which is useful in some contexts.

4) Although anonymous unions are supported by ISO C++, anonymous structs are not. Nevertheless, most compilers have extensions that allow anonymous structs, and the combination of both allows you to do magic like this:

struct vector4{  union {    float data[4];    struct {       float x,y,z,w;    };  };};vector4 v = {{1,2,3,4}};assert( v[0] == v.x );


unions can be significantly more general than this, having their own constructors, destructors, member functions...although I'm not aware of any reasons to use those features.
Quote:Original post by direwulf
2) They are sometimes used essentially as a replacement reinterpret_cast, although I believe this may technically be bad behavior.


In that context, afaik, they are the only sanctioned way to do type-punning (without aliasing issues).

int x;float y = *reinterpret_cast<float*>(&x); // obvious aliasing

int x;float y = reinterpret_cast<float&>(x); // less obvious aliasing

int x;float y = *(float*)&x; // same as first


Instead, either rethink your algorithm, or use an union:

 int x;union { int as_int; float as_float } const punned = {x};
Language lawyer alert:
Quote:In that context, afaik, they are the only sanctioned way to do type-punning (without aliasing issues).

C99's J.1 says "The value of a union member other than the last one stored into [is unspecified]". There are two aliasing-proof and sanctioned ways to perform type punning:
- assemble the desired type by loading char values and shifting them according to the processor's byte order;
- use memcpy(). This communicates the intent clearly and avoids any runtime penalty (ICC11 is studly enough to replace it with a sequence of move instructions).
That said, union_cast is explicitly allowed by GCC because it is so widespread.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3

This topic is closed to new replies.

Advertisement