4

Suppose I have an enum:

enum class Thing : std::uint8_t {
  Foo = 21,
  Bar = 42,
  Baz = 1
};

I want to convert a "raw" value (of the underlying type) to a value of that enum, with error handling catching values which are not "a thing". I could use checks like if (raw_value == static_cast<std::uint8_t>(Thing::Foo)) and then an else with the error handling, but then I could forget for example Thing::Baz. However, when I switch over a value of type Thing, then my compiler (as probably most modern compilers) warns me about unhandled enumeration values ("enumeration value Baz not handled in switch").

So I came up with this:

Thing thingFromUInt8(std::uint8_t const b) {
  Thing const t = static_cast<Thing>(b);
  switch (t) { // If I'd add Thing::Frob but forget it here I get a warning
    case Thing::Foo:
    case Thing::Bar:
    case Thing::Baz:
      return t;
  }
  throw std::runtime_error("That's not a thing...");
}

Questions:

  • Is this "legal" C++ (C++11 and above)?
  • If it is, does it have any drawbacks?
Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
  • 2
    It is legal C++. It is a bit verbose, you need to write a lot, but leveraging the compiler warnings in the `switch` is a good idea. BTW, I think your question better belongs on https://codereview.stackexchange.com/. – Werner Henze Feb 21 '21 at 09:57
  • It's *legal*, but if you're asking whether a warning (or some diagnostic) is guaranteed, I don't think it is. – cigien Feb 21 '21 at 16:26
  • https://stackoverflow.com/a/18195408/1116364 This also answers the legality; adding here for reference – Daniel Jour Feb 24 '21 at 07:18

1 Answers1

2

It is legal C++.

The drawback is the DRY violation, but avoiding it is difficult.

In we'll have reflection and be able to generate equivalent code (without having to rely on compiler warnings to make sure we didn't miss any). Reflection syntax is still a bit in flux, but every version I have read over was able to handle that problem.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524