Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Underlying type of weak typed enum in C++11

Tags:

c++

c++11

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?

like image 684
prapin Avatar asked Jan 06 '13 18:01

prapin


People also ask

What is the underlying type of an enum?

Each enum type has a corresponding integral type called the underlying type of the enum type. This underlying type shall be able to represent all the enumerator values defined in the enumeration. If the enum_base is present, it explicitly declares the underlying type.

What is the default underlying type of each element in an enum?

The default underlying type of the enumeration elements is int. By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1. Enums are enumerated data type in C#.

What is enum underlying type in C++?

The type of a C++ enum is the enum itself. Its range is rather arbitrary, but in practical terms, its underlying type is an int . It is implicitly cast to int wherever it's used, though.

What is underlying type in C?

The only requirements in the C++03 standard are that the underlying type is an integral type that can represent all the enumerator values defined in the enumeration, and that the underlying type is not larger than int, unless the value of an enumerator cannot fit in an int or unsigned int.


1 Answers

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)

like image 159
GManNickG Avatar answered Nov 08 '22 14:11

GManNickG