How would you go about doing this in standard C++11/14 ? Because if I'm not mistaken this isn't standard compliant code with the anonymous structs.
I wish to access the members the same way as you would with this.
template <typename some_type>
struct vec
{
union {
struct { some_type x, y, z; };
struct { some_type r, g, b; };
some_type elements[3];
};
};
I think the other answers sort of missed the point of the question:
In other words, the question is really "how do I define a type
vec
in a standard-compliant manner such that given an objectu
of that type,u.x
,u.r
, andu.elements[0]
all refer to the same thing?"Well, if you insist on that syntax...then the obvious answer is: references.
So:
The first problem with this approach is that you need extra space for 6 reference members - which is rather expensive for such a small struct.
The second problem with this approach is that given
const vec<double> v;
,v.x
is still of typedouble &
, so you could writev.x = 20;
and have it compile without warning or error - only to get undefined behavior. Pretty bad.So, in the alternative, you might consider using accessor functions:
You would have to write
u.x()
etc. instead ofu.x
, but the space savings is considerable, you can also rely on the compiler-generated special member functions, it's trivially copyable ifsome_type
is (which enables some optimizations), it's an aggregate and so can use the aggregate initialization syntax, and it's also const-correct.Demo. Note that
sizeof(vec<double>)
is 72 for the first version and only 24 for the second.Yes, neither C++11 nor C++14 allow anonymous structs. This answer contains some reasoning why this is the case. You need to name the structs, and they also cannot be defined within the anonymous union.
§9.5/5 [class.union]
So move the struct definitions outside of the union.
Now, we require
some_type
to be standard-layout because that makes all the members of the anonymous union layout compatible. Here are the requirements for a standard layout type. These are described in section §9/7 of the standard.Then, from §9.2 [class.mem]
And for the array member, from §3.9/9 [basic.types]
To ensure that
some_type
is standard layout, add the following within the definition ofvec
std::is_standard_layout
is defined in thetype_traits
header. Now all 3 members of your union are standard layout, the two structs and the array are layout compatible, and so the 3 union members share a common initial sequence, which allows you to write and then inspect (read) any members belonging to the common initial sequence (the entire thing in your case).Anonymous unions are allowed in C++11/14. See the example of their usage at Bjarne Stroustrup's C++11 FAQ
Regarding anonymous structs see Why does C++11 not support anonymous structs, while C11 does? and Why does C++ disallow anonymous structs and unions?
Though most compilers support anonymous structs, if you want your code to be standard compliant you have to write something like this: