Reputation: 3164
Hello I have this from C++ primer 5th edition:
// unscoped enumeration; the underlying type is machine dependent
enum Tokens {INLINE = 128, VIRTUAL = 129};
void newf(unsigned char);
void newf(int);
unsigned char uc = VIRTUAL;
newf(VIRTUAL); // calls newf(int)
newf(uc); // calls newf(unsigned char)
The
enum
Tokens has only two enumerators, the larger of which has the value129
. That value can be represented by the typeunsigned char
, and many compilers will useunsigned char
as the underlying type for Tokens. Regardless of its underlying type, objects and the enumerators ofTokens
are promoted toint
. Enumerators and values of anenum
type are not promoted tounsigned char
, even if the values of the enumerators would fit.
But If I explicitly specify the underlying type that matches exactly the integral value of the function parameter, then I think no implicit conversion will take place:
enum days : unsigned char{sat = 1, sun, mon, tue, wed, thu, fri};
void foo(unsigned char x){
std::cout << "foo(unsigned char)\n";
}
void foo(int){
std::cout << "foo(int)\n";
}
foo(tue); // foo(unsigend char)
So as you can see the enumerator value tue
is not promoted to int
and I get the version of foo(unsigned char)
and not foo(int)
.
So does he mean if the enumeration underlying type differs from the function parameter then enumerators are not promoted to char
but to int
or large integral types?
I think in his example of enum tokens
if the underlying type is unsigned char
then there will be no integral promotion in the function call: newf(VIRTUAL); // calls newf(int)
and the version of newf(unsigned char)
is selected. What you think?
Upvotes: 1
Views: 247
Reputation: 5565
From cppreference's description of enums:
Values of unscoped enumeration type are implicitly-convertible to integral types. If the underlying type is not fixed, the value is convertible to the first type from the following list able to hold their entire value range:
int
,unsigned int
,long
,unsigned long
,long long
, orunsigned long long
, extended integer types with higher conversion rank (in rank order, signed given preference over unsigned) (since C++11). If the underlying type is fixed, the values can be converted to their underlying type (preferred in overload resolution), which can then be promoted.
So you're right about which overload of foo
will be selected, but you're wrong that there's no implicit conversion taking place. A days
is still a different type from an unsigned char
, but it will implicitly convert to one.
You're also wrong that, in the event that the implementation happens to select unsigned char
as the underlying type for enum Tokens
, it will therefore implicitly convert to unsigned char
. Implicit conversion to a narrower underlying type than int
only occurs if you fix the underlying type yourself instead of letting the implementation decide.
The text from the Primer you quoted is only describing the situation when you don't explicitly specify an underlying type.
Quotes from the draft standard, expr.conv.prom:
A prvalue of an unscoped enumeration type whose underlying type is not fixed can be converted to a prvalue of the first of the following types that can represent all the values of the enumeration ([dcl.enum]):
int
,unsigned int
,long int
,unsigned long int
,long long int
, orunsigned long long int
. If none of the types in that list can represent all the values of the enumeration, a prvalue of an unscoped enumeration type can be converted to a prvalue of the extended integer type with lowest integer conversion rank ([conv.rank]) greater than the rank oflong long
in which all the values of the enumeration can be represented. If there are two such extended types, the signed one is chosen.A prvalue of an unscoped enumeration type whose underlying type is fixed ([dcl.enum]) can be converted to a prvalue of its underlying type. Moreover, if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type.
And from over.ics.rank:
A conversion that promotes an enumeration whose underlying type is fixed to its underlying type is better than one that promotes to the promoted underlying type, if the two are different.
Upvotes: 3