MK.
MK.

Reputation: 34527

c++ enum can compare to integer but not assign from integer?

#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.

Upvotes: 3

Views: 3114

Answers (3)

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29023

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 for the value being converted. 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.

Upvotes: 10

NathanOliver
NathanOliver

Reputation: 180490

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);

Upvotes: 1

Pete Becker
Pete Becker

Reputation: 76245

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.

Upvotes: 1

Related Questions