3
#include <iostream>

enum mode { MODE0=0, MODE1, NUM_MODES};

int main(int args, char ** argv) {
  int i = 1;
  std::cout << (i == MODE0 ? "true" : "false") << "\n";
  std::cout << (i == MODE1 ? "true" : "false") << "\n";
  mode test;
  test = i; // error
}

Why is it that the comparison of i to enum values works fine, but I get compilation error when assigning mode test variable to an integer value?

enum.cc:10:8: error: invalid conversion from 'int' to 'mode' [-fpermissive]

My question is specifically about why comparison works and assignment doesn't (not how to fix my code) and it has received a couple of good explanations below.

MK.
  • 33,605
  • 18
  • 74
  • 111
  • 1
    You have to cast it before assign. https://stackoverflow.com/questions/11452920/how-to-cast-int-to-enum-in-c – MNF Jun 29 '17 at 18:09
  • 1
    You would need to `static_cast` it to get it to work – Curious Jun 29 '17 at 18:09
  • Possible duplicate of [using enum says invalid conversion from 'int' to 'type'](https://stackoverflow.com/questions/8703743/using-enum-says-invalid-conversion-from-int-to-type) – Akaahn Jun 29 '17 at 18:10

3 Answers3

9

MODE0, MODE1 and NUM_MODES are guaranteed to be convertible to int (the underlying type of the enum) but the reverse is not true. Not all int can be converted to mode. For example, what is the matching mode for the int 42? Simply put, only the implicit conversion from enum to int is defined, the opposite implicit conversion is not defined.

If you want to convert from int to mode you can preform a static_cast to signal that you are taking the responsibility of ensuring that the value being converted is always legal to convert to mode. Try

test = static_cast<mode>(i);

You can use strongly typed enumerations by adding the class keyword to your enum to prevent any implicit casts and to limit the scope of the enum value names. The definition would look like enum class mode { MODE0 = 0, MODE1, NUM_MODES };. In this case, you must quality the enum value names, for example, you would need to use mode::MODE0 instead of MODE0. This has the advantage that it avoids name collisions.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
1

It's because there is a conversion from an enumerated type to int but there is no conversion in the opposite direction. For the comparison, MODE0 gets promoted to int. For the assignment, i would have to be converted to mode.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
1

Look at it this way. When you do a comparison it doesn't matter if the int is not a valid possible value. If it is not then the comparison will fail and we can go on. Now when we go and try to assign an int to an enum you could assign to it a value that isn't mapped to the enum values. Since we don't want this implicitly happening the conversion is invalid. If you want to tell the compiler that it is okay, you know what you are doing, then you can cast it like:

test = static_cast<mode>(i);
NathanOliver
  • 171,901
  • 28
  • 288
  • 402