Принудительное перечисление с беззнаковым длинным типом
Можно ли заставить базовый тип перечисления быть беззнаковым длинным типом? Благодаря
Ответы
Ответ 1
В С++ 03 нет способа заставить перечисленный тип иметь какую-либо конкретную базовую реализацию. Введите спецификацию С++ и раздел 7.2/5:
Основной тип перечисления является интегральным типом, который может представлять все значения перечисления, определенные в перечислении. Определяется реализация, тип интеграла используется как базовый тип для перечисления, за исключением того, что базовый тип не должен быть больше, чем int, если значение перечислителя не может быть помещено в int или unsigned int. Если список перечислений пуст, базовый тип выглядит так, как если бы перечисление имело один перечислитель со значением 0. Значение sizeof(), применяемое к типу перечисления, объекту типа перечисления или перечислителю, является значением sizeof() применяется к базовому типу.
Это довольно слабое условие и говорит, что вы не только не можете знать тип, но и потому, что он не определен, он не гарантирует, что он даже соответствует одному из примитивных типов вообще.
Однако в С++ 0x они исправляют это, чтобы вы могли явно указать, какой тип вы хотите:
enum MyEnumeration: unsigned long {
/* ... values go here ... */
};
Это позволит вам явно управлять базовым типом.
Ответ 2
Это может быть достигнуто в зависимости от вашего компилятора.
Он не работает с Windows MSVS, но я тестировал его и работал со следующими версиями компилятора gcc/g++ (plus embedded cpp):
- mipsel-openwrt-linux-uclibc-gcc.bin(OpenWrt/Linaro GCC 4.8-2014.04 r47072) 4.8.3
- g++ (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.4) 5.4.0 20160609
- gcc (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.4) 5.4.0 20160609
- avr-g++. exe (AVR_8_bit_GNU_Toolchain_3.5.4_1709) 4.9.2
Определив одно из ваших перечислений на значение, которое будет представлено в длинном значении, в некоторых компиляторах он принудительно привязал его к такому размеру. Вышеуказанный код обычно выводит:
8
4
4
Источник:
#include <iostream>
using namespace std;
typedef enum
{
ENUM_11,
ENUM_12,
enum1_force_long = 0x1122334455667788
} LongEnum1_t;
typedef enum
{
ENUM_21,
ENUM_22,
enum2_force_long = 0x11223344
} LongEnum2_t;
typedef enum
{
ENUM_31,
ENUM_32,
enum3_force_long = 0x1122
} LongEnum3_t;
LongEnum1_t enum1;
LongEnum2_t enum2;
LongEnum3_t enum3;
int main(void)
{
cout << sizeof(enum1) << endl;
cout << sizeof(enum2) << endl;
cout << sizeof(enum3) << endl;
return 0;
}
Ответ 3
Начиная с С++ 11 вы можете сделать enum MyEnum: unsigned long
вот так:
enum Color : int { red, green, blue };
Color r = red;
switch(r)
{
case red : std::cout << "red\n"; break;
case green: std::cout << "green\n"; break;
case blue : std::cout << "blue\n"; break;
}
Ссылка: здесь