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];
};
};
An anonymous union is a union without a name. It cannot be followed by a declarator. An anonymous union is not a type; it defines an unnamed object. The member names of an anonymous union must be distinct from other names within the scope in which the union is declared.
A Microsoft C extension allows you to declare a structure variable within another structure without giving it a name. These nested structures are called anonymous structures.
In C++17 and later, the std::variant class is a type-safe alternative for a union. A union is a user-defined type in which all members share the same memory location. This definition means that at any given time, a union can contain no more than one object from its list of members.
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]
...
The member-specification of an anonymous union shall only define non-static data members. [ Note: Nested types, anonymous unions, and functions cannot be declared within an anonymous union. —end note ]
So move the struct definitions outside of the union.
template <typename some_type>
struct vec
{
struct xyz { some_type x, y, z; };
struct rgb { some_type r, g, b; };
union {
xyz a;
rgb b;
some_type elements[3];
};
};
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]
16 Two standard-layout struct (Clause 9) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types (3.9).
18 If a standard-layout union contains two or more standard-layout structs that share a common initial sequence, and if the standard-layout union object currently contains one of these standard-layout structs, it is permitted to inspect the common initial part of any of them. Two standard-layout structs share a common initial sequence if corresponding members have layout-compatible types and either neither member is a bit-field or both are bit-fields with the same width for a sequence of one or more initial members.
And for the array member, from §3.9/9 [basic.types]
...
Scalar types, standard-layout class types (Clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called standard-layout types.
To ensure that some_type
is standard layout, add the following within the definition of vec
static_assert(std::is_standard_layout<some_type>::value, "not standard layout");
std::is_standard_layout
is defined in the type_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:
template <typename some_type>
struct vec
{
union {
struct { some_type x, y, z; } s1;
struct { some_type r, g, b; } s2;
some_type elements[3];
};
};
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