Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous union and struct [duplicate]

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];
    };
};
like image 217
Grandstack Avatar asked Aug 28 '14 06:08

Grandstack


People also ask

What is an anonymous union?

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.

What is an anonymous struct?

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.

What is a C++ union?

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.


2 Answers

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).

like image 82
Praetorian Avatar answered Sep 21 '22 09:09

Praetorian


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];
    };
};
like image 30
Anton Savin Avatar answered Sep 22 '22 09:09

Anton Savin