5
enum class pid
{
    Alpha, Beta, Gamma
};

int main()
{
    int propId = 2;
    switch(propId)
    {
    case pid::Alpha:
    case pid::Beta:
    case pid::Gamma:
        break;
    }
}

Above snippet compiles fine in msvc2012 (and works) but fails in clang-3.4 and g++-4.8. These require static_cast<pid>(propId) to be used inside switch clause.

Incidentally, simple assignment without explicit cast such as pid a = propId; gives error in each compiler.

Which one got it right?

dyp
  • 38,334
  • 13
  • 112
  • 177
kozmo
  • 51
  • 1
  • 4

1 Answers1

6

The standard Clause 4, "standard conversions", only every lists unscoped enumerations. Therefore, strong enums do not have any standard conversions, and you must use the static_cast in either direction.

You could argue that this sort of explicitness is the entire point of the strong enums. They do not act as integers at the drop of a hat, but rather require explicit declaration of intent. Note [thanks, @DyP] that switch statements explicitly support strong enums and do not require a manual conversion to some integral type.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • You could also quote [stmt.switch]. – dyp Jan 01 '14 at 16:14
  • Actually, it would be neat if the standard defined a static member `at()` that would convert an underlying-type value into the enum in question and throw a range exception. – Kerrek SB Jan 01 '14 at 16:14
  • @LightnessRacesinOrbit: No seriously - *everyone* and their dog reinvent wheels to validate and print enums. At least the validation part can be done better by the compiler than by reinvention, don't you think? – Kerrek SB Jan 01 '14 at 17:55
  • @KerrekSB: Yeah but I wish people wouldn't use enums like that _at all_. I see benefits when de-serialising and that's about it. – Lightness Races in Orbit Jan 01 '14 at 17:58
  • @LightnessRacesinOrbit Sometimes you are interfacing with other languages that do not have enums. You get an input integer, that you want to convert to an enum, cause you like to use those in your C++ code. Then you are force to use a switch statement, while something like `template EType std::to_enum(typename std::unerlying_type::type i)` would help.. – bartgol Jan 30 '18 at 18:47
  • I'm not arguing for this feature to be added somewhere in the library. I just saw your comment, and I just thought I'd point out a case where one *does* use enums like that. I agree that it is a corner case. Still, some of us need to deal with cross language code a lot. :) – bartgol Jan 30 '18 at 22:59