Consider the following piece of code:
struct S { union { int arr1[10]; char arr2[sizeof(arr1)]; }; };
It compiles successfully with gcc 4.9.2 in c++03 and c++11 mode. However when I change S
to be a template like so:
template <size_t N> struct S { union { int arr1[N]; char arr2[sizeof(arr1)]; }; };
I get the following error output:
error: int S<10ul>::<anonymous union>::arr1 [10]’ is inaccessible
int arr1[N];
error: within this context
char arr2[sizeof(arr1)];
Clang compiles both versions only in c++11 mode. I am curious what is the correct behavior here. Maybe should I explicitly state that arr2
size is sizeof(int) * N
?
When we declare a union, memory allocated for a union variable of the type is equal to memory needed for the largest member of it, and all members share this same memory space. In above example, "char arr[8]" is the largest member. Therefore size of union test is 8 bytes.
The alignment of your union must be the largest alignment of any of its members. This is 4. Therefore, the size of the union must be aligned to that size. It could have been 5 (as c is the largest member of the union), but because the alignment of the union as a whole is 4, the size of the union is padded to 8.
However, the size of uJob is 32 bytes. It's because the size of a union variable will always be the size of its largest element. In the above example, the size of its largest element, ( name[32] ), is 32 bytes. With a union, all members share the same memory.
Your union is anonymous. Thus, the compiler will create arr1
and arr2
at class-level.
Because of this, char arr2[sizeof(arr1)];
won't refer to arr1
properly.
Here is a workaround :
template <size_t N> struct S { union A { int arr1[N]; char arr2[sizeof(arr1)]; }; };
Compiles fine here : https://ideone.com/JcvOYg
By naming the union, we prevent the compiler from including it directly. It is then able to retrieve arr1
properly.
But it also means that arr1
and arr2
aren't not S
's members anymore.
Finally, Members can be defined in terms of other members
but the latter has to be "findable" by the compiler.
You can do this:
template <size_t N> class S { private: union { int arr1[N]; char arr2[N*sizeof(int)]; }; };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With