Consider the following piece of code
#include <iostream>
using namespace std;
enum myEnum { a, b, c };
void test(myEnum e) {
cout << "myEnum overload" << endl;
}
void test(unsigned int i) {
cout << "unsigned int overload" << endl;
}
int main() {
test(a);
test(1);
test(1u);
return 0;
}
(I know enum class
is safer than enum
for this kind of things but I am using open-source code that has old-style enums.)
When I compile this with g++ 4.4.7 and run it, I get
myEnum overload
unsigned int overload
unsigned int overload
i.e. the compiler prefers to convert int
to unsigned int
over converting it to myEnum
. This is what I want, but I was wondering if this is always guaranteed. The standard does not specify exactly what the underlying type of myEnum
should be, so I thought perhaps if it was exactly int
, perhaps this would be favored over unsigned int
.
But when I comment out the unsigned int
overload, I get this error:
enum_overload.cpp: In function ‘int main()’:
enum_overload.cpp:17: error: invalid conversion from ‘int’ to ‘myEnum’
enum_overload.cpp:17: error: initializing argument 1 of ‘void test(myEnum)’
enum_overload.cpp:18: error: invalid conversion from ‘unsigned int’ to ‘myEnum’
enum_overload.cpp:18: error: initializing argument 1 of ‘void test(myEnum)’
Does that mean that old-style enums implicitly convert to their underlying types but not from those types? If that is the case, then that would answer my previous question: if integral types can't convert to myEnum
, then the overload resolution is guaranteed to behave as above.
[conv.integral]/1:
A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
The converse is not true. There's no implicit conversion from an integer type to an unscoped enum type:
It seems that you are confusing this with casting an integral value to an enum type: [expr.static.cast]/10
A value of integral or enumeration type can be explicitly converted to a complete enumeration type. The value is unchanged if the original value is within the range of the enumeration values ([dcl.enum]). Otherwise, the behavior is undefined. A value of floating-point type can also be explicitly converted to an enumeration type. The resulting value is the same as converting the original value to the underlying type of the enumeration ([conv.fpint]), and subsequently to the enumeration type.
(emphasis mine)
But this can only be done via an explicit cast:
E x1 = static_cast<E>(1) // yes
E x2 = E(1); // yes
E x3 = 1; // no
E x4(1); // no
I suggest you read this link.
As mentioned,
An enumeration such as
enum Color { red, white, blue };
is its own type. It is not of typeint
.
myEnum
is neither an int
nor an unsigned int
.
Plus, I suggest not to use myEnum
by directly casting an int
to a myEnum
(doing this: test(static_cast<myEnum>(0))
).
Indeed the compiler won't check for you if the value provided is a valid one, it can lead to unexpected behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With