Можно ли указать ширину бита перечисления в С++ 11?
Я обмениваю пакеты со встроенным устройством, и мне бы очень хотелось иметь возможность использовать перечисления в подбайтовых частях определений пакетов. Но я не могу угадать синтаксис, который мог бы работать, и я подозреваю, что это невозможно, так как я не могу понять, как объявить частичный байтовый подтип в С++:
enum class communication_path_t : uint8_t {
Ethernet = 0, Wifi = 1
};
typedef struct {
communication_path_t pathByte; // works, uses one byte
// ...
// single byte split three ways
uint8_t retryCount : 3;
communication_path_t path : 3; // compile error
uint8_t deviceType : 2;
} packet_t;
Это не компилируется, потому что вы не можете поместить 8-битное перечисление в 3-битное поле. Отредактировано в точной ошибке:
<anonymous struct>::path’ is too small to hold all values
of ‘enum class MyNamespace::communication_path_t’ [-Werror]
Что бы я хотел сделать, это примерно так:
enum class communication_path_t : uint8_t : 3 { ...
или
typedef uint8_t:3 three_bit_int_t;
enum class communication_path_t : three_bit_int_t { ...
Ни один из них не компилируется, и у меня возникают проблемы с поиском документации, которая ссылается как на битовые поля, так и на перечисления, из-за чего я подозреваю, что их нет. Прежде чем я буду смотреть на часы, что я пытаюсь сделать даже возможно?
Изменить: обновление до g++ - 4.9 не устраняет проблему. Это замечательно безболезненно, просто:
sudo apt-get install g++-4.9
g++-4.9 --version
g++-4.9 (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2
GCC 4.9.2 released [2014-10-30]
Затем измените мою цепочку построения, чтобы использовать "g++ - 4.9" вместо "g++". К сожалению, я получаю ту же ошибку:
g++-4.9 -Dlinux -std=c++11 -pthread (...) ../common/LogPacketBreakdown.cpp
In file included from ../common/LogPacketBreakdown.cpp:12:0:
../common/PacketInfo.h:104:50: error: ‘Digiflex::<anonymous
struct>::communicationPath’ is too small to hold all values of
‘enum class Digiflex::communication_path_t’ [-Werror]
communication_path_t communicationPath : 3;
Похоже, мне нужно 5.0 и это не в списке экспериментальных инструментов Ubuntu, поэтому мне нужно будет строить из исходного кода. Я думаю, что сейчас буду жить с обходным решением. Спасибо всем за вашу помощь.
Ответы
Ответ 1
Код, который вы опубликовали, должен быть принят самыми последними компиляторами. Вы можете увидеть этот отчет об ошибке, где должно произойти исправление: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51242
В сегодняшнем gcc предупреждение все равно должно быть выпущено. В clang вы ничего не увидите.
Ответ 2
Нет, нет никакого пути к typedef
битовому полю в С++, даже с типом перечисления.
Bitfield-ness - это свойство объявлений переменных-членов, оно вообще не поддерживается системой типов.
Но ваш первый пример отлично. Как отмечает Билл, это ошибка GCC, а разработчики GCC отмечают, это только предупреждение с 2013 года. Обходным путем является использование int path : 3;
и для преобразования значений перечисления или вообще не использовать enum
.
Ответ 3
Он работает хотя бы от g++ 4.8 на debian, поэтому я предполагаю также на ubuntu.
Компилятор дает только предупреждение, ошибка в этом случае была обложена опцией -Werror компилятора. Рекомендуется настроить -Werror для переполнения, поскольку это будет сообщено при назначении значения перечисления, которое не соответствует битовому полю.