4
#include <iostream>    

typedef enum my_time {
  day,
  night
} my_time;

int main(){    
  // my_time t1 = 1; <-- will not compile
  int  t2 = night;
  return 0;  
} 

How is it expected that I can assign an enum value to an int but not the other way in C++?

Of course this is all doable in C.

Dan
  • 577
  • 1
  • 3
  • 9
  • 3
    Use `static_cast`: _e.g._ `my_time t1 = static_cast(1);` also note that you should not normally need to do this. It's useful for times when you have no choice, but in general it's better to avoid that in your design. – paddy Jul 08 '20 at 01:53
  • You might want to also read this: https://stackoverflow.com/questions/18335861/why-is-enum-class-preferred-over-plain-enum – paddy Jul 08 '20 at 01:58
  • 3
    you don't need to typedef enum or struct/class in C++ – phuclv Jul 08 '20 at 02:55

4 Answers4

4

Implicit conversions, or conversions in general, are not mutual. Just because a type A can be converted to a type B does not imply that B can be converted to A.

Old enums (unscoped enums) can be converted to integer but the other way is not possible (implicitly). Thats just how it is defined. See here for details: https://en.cppreference.com/w/cpp/language/enum

Consider that roughly speaking enums are just named constants and for a function

void foo(my_time x);

It is most likely an error to pass an arbitrary int. However, a

void bar(int x);

can use an enum for special values of x while others are still allowed:

 enum bar_parameter { NONE, ONE, MORE, EVEN_MORE, SOME_OTHER_NAME };
 bar(NONE);
 bar(SOME_OTHER_NAME);
 bar(42);

This has been "fixed" in C++11 with scoped enums that don't implicitly convert either way.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
2

  You could cast to int. This expression makes an explicit conversion of the specified data type (int) and the given value (night).

 int t2 = static_cast<int>(night)
user11717481
  • 1
  • 9
  • 15
  • 25
2

Of course this is all doable in C

That doesn't mean that the minds behind C++ automatically consider it a desired behavior. Nor should they have such an attitude. C++ follows its own philosophy with regard to types. This is not the only aspect where a conscious decision was made to be more strongly typed than C. This valid C snippet is invalid in C++

void *vptr = NULL;
int  *iptr = vptr; // No implicit conversion from void* to T* in C++

How is it expected that I can assign an enum value to an int but not the other way in C++?

It's the behavior because one side of the conversion is less error prone. Allowing an enumerator to become an integer isn't likely to break any assumptions the programmer has about an integer value.

An enumeration is a new type. Some of the enmueration's values are named. And for most cases of using an enumeration, we really do want to restrict ourselves to those named constants only.

Even if an enumeration can hold the integer value, it doesn't mean that value is one of the named constants. And that can easily violate the assumptions code has about its input.

// Precondition: e is one of the name values of Enum, under pain of UB
void frombulate_the_cpu(Enum e);

This function documents its precondition. A violation of the precondition can cause dire problems, that's what UB usually is. If an implicit conversion was possible everywhere in the program, it'd be that more likely that we violate the precondition unintentionally.

C++ is geared to catch problems at compile time whenever it can. And this is deemed problematic.

If a programmer needs to convert an integer an enumeration, they can still do it with a cast. Casts stand out in code-bases. They require a conscious decision to override a compiler's checks. And it's a good thing, because when something potentially unsafe is done, it should be with full awareness.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
1

Cast the int when assigning . . .

my_time t1 = (my_time)1;
tzg
  • 616
  • 1
  • 8
  • 17