Reputation: 6858
C++11 introduced strongly typed enums, with the syntax enum class
. These are not compatible with integer types and require explicit casts to obtain their numeric value. C++11 also introduces the ability to specify the storage class for weakly typed enums with the form enum name : type {}
. This is fine up to here.
But it looks like even if an weakly typed enum has a given storage class, the type of its items is still int
. I tried with Visual Studio 2012, November CTP release. Consider the following code:
enum charEnum : char { A = 'A' };
enum longEnum : long long { Tera = 1000000000000 };
void fct(char val) {}
void fct(int val) {}
void fct(long long val) {}
int main()
{
static_assert(sizeof(A) == sizeof(char), "check charEnum size");
static_assert(sizeof(Tera) == sizeof(long long), "check longEnum size");
fct('A'); // calls fct(char)
fct(1); // calls fct(int)
fct(2ll); // calls fct(long long)
fct(A); // calls fct(int) !
fct(Tera); // calls fct(int), with truncation !
fct((long long)Tera); // calls fct(long long)
return 0;
}
The overloaded function called for an enumeration value is always fct(int)
, even if this results in a truncation of the value. Of course, with an explicit cast, we can call the overloaded function, but this was also possible in traditional C++03 syntax.
Am I missing something obvious? Why is that? Is there a better workaround than an explicit cast?
Upvotes: 12
Views: 2048
Reputation: 503805
It's a compiler bug. According to §7.2/9 and §4.5/4:
§7.2/9:
The value of an enumerator or an object of an unscoped enumeration type is converted to an integer by integral promotion (4.5)§4.5/4:
A prvalue of an unscoped enumeration type whose underlying type is fixed (7.2) 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.
The last one should convert to long long
, not int
. The char
case is a point of contention. (!)
Test program:
#include <iostream>
enum charEnum : char { A = 'A' };
enum longEnum : long long { Tera = 1000000000000 };
void fct(char val) { std::cout << "fct(char)" << std::endl; }
void fct(int val) { std::cout << "fct(int)" << std::endl; }
void fct(long long val) { std::cout << "fct(long long)" << std::endl; }
int main()
{
static_assert(sizeof(A) == sizeof(char), "check charEnum size");
static_assert(sizeof(Tera) == sizeof(long long), "check longEnum size");
fct('A');
fct(1);
fct(2ll);
fct(A);
fct(Tera);
fct((long long)Tera);
}
MSVC2012NovCTP output:
fct(char)
fct(int)
fct(long long)
fct(int)
fct(int)
fct(long long)
g++ 4.7.1:
fct(char)
fct(int)
fct(long long)
fct(int)
fct(long long)
fct(long long)
Upvotes: 9