1

I wanted to have a struct that can be accessed both as an array and as named members. I wrote this:

struct RangeLimits
{
  enum class RangePenalty: byte
  {
    OUT_OF_RANGE,
    NO_PENALTY,
    SHORT,
    MEDIUM,
    LONG,
    EXTREME
  };
  union
  {
    struct
    {
      range shrt;
      range med;
      range lon;
      range ext;
    };
    std::array<range, 4> arang;
  };
};

namespace static_test
{

constexpr static bool checkThatArrayMapsToFields()
{
  RangeLimits limits{ range{1},range{1},range{1},range{1} };
  limits.med = range{ 66 };
  return limits.arang[1] == range{ 66 };
}

static_assert(checkThatArrayMapsToFields(), "Union not behaving as expected");

range is really just unsigned char. I am getting this error:

1>RangeLimits.h(41,41): error C2131: expression did not evaluate to a constant
1>RangeLimits.h(38,16): message : failure was caused by accessing a non-active member of a union
1>RangeLimits.h(38,16): message : see usage of 'techsheet::RangeLimits::arang'

I do understand this is how unions are supposed to behave in C++ (well, now I do anyway). But I do not understand why does C++ care, why this rule even exists. After all, you can't always check this anyway.

timrau
  • 22,578
  • 4
  • 51
  • 64
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • 1
    "range is really just unsigned char" > why not put it in your code snippet then? – Nelfeal Jul 16 '23 at 12:32
  • 2
    Pretty sure the answer you are looking for is [here](https://stackoverflow.com/questions/46933166/rationale-behind-active-members-of-unions). – Nelfeal Jul 16 '23 at 12:33
  • 1
    ^^^ If not a dupe, I am tempted to close this. Accessing non active members is finally the same as using `reinterpret_cast` or c-style casts, and are explicitly stated as _undefined behavior_. – πάντα ῥεῖ Jul 16 '23 at 12:37
  • 2
    As for what to do instead: since you only want to provide different ways to access the *same* data, you should just use functions. Keep the array as your data storage, but provide access through, for example, `range& shrt() { return arang[0]; }`. – Nelfeal Jul 16 '23 at 12:40

0 Answers0