11

I have a union declared like that:

union
{
    int all[4];
    struct
    {
        int a, b, c, d;
    };
};

The point of the all array is simply to make iteration over the 4 fields simpler.

To make it even simpler, I'd like to replace it with an std::array<int, 4>. Would that expose me to nasal demons?

Xeo
  • 129,499
  • 52
  • 291
  • 397
zneak
  • 134,922
  • 42
  • 253
  • 328

1 Answers1

8

First, it's important to note that merely having two objects of different types in a union is never undefined. What's undefined is to write to one and read from another, with one exception:

[C++11: 9.5/1]: [ Note: One special guarantee is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout structs that share a common initial sequence (9.2), and if an object of this standard-layout union type contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of standard-layout struct members; see 9.2. —end note ] [..]

Now, although it's not written out specifically anywhere that std::array fits this rule, the fact that it's an aggregate with only element members seems enough of a guarantee:

[C++11: 23.3.2.1/2]: An array is an aggregate (8.5.1) that can be initialized with the syntax:

   array<T, N> a = { initializer-list };

where initializer-list is a comma-separated list of up to N elements whose types are convertible to T.

So, it's safe not only to have the union exist in the first place, but also to read and write to either member at will.

Therefore, my conclusion is: yes; it is safe.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    To reduce confusion, I've changed the title to "is it *safe* to ...", so I edited the "no; it is safe" into "yes; it is safe". – zneak Feb 13 '14 at 18:55
  • 1
    Maybe it's _not_ enough. Turns out layout-compatibility is extremely restrictive. If nothing else, actually, four `int`s is not a standard-layout struct. – Lightness Races in Orbit Feb 13 '14 at 19:41
  • 1
    Wait, `struct { int a,b,c,d; }` is not standard layout? Them's fighting words. – Yakk - Adam Nevraumont Feb 13 '14 at 20:53
  • 2
    I don't think it's guaranteed that `std::array` is a standard-layout class, and I'm not sure if it's guaranteed that struct with four `int` data members is layout-compatible to a raw array. – dyp Feb 13 '14 at 20:55
  • @Yakk: I believe the question is whether `int a,b,c,d` _not in a `struct`_ are layout-compatible with the `struct` you described. That's a whole new thing. – Lightness Races in Orbit Feb 14 '14 at 01:53
  • 2
    For what it's worth, [according to g++](http://ideone.com/7WFcu3), the union itself is standard-layout, which transitively means that it considers that both `std::array` and the "inline struct" are. If g++'s `is_standard_layout` conforms to the standard, then this construct should be safe. – zneak Feb 14 '14 at 16:49