Подтвердить что ты не робот

Можно ли указать ширину бита перечисления в С++ 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, поэтому мне нужно будет строить из исходного кода. Я думаю, что сейчас буду жить с обходным решением. Спасибо всем за вашу помощь.

4b9b3361

Ответ 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 для переполнения, поскольку это будет сообщено при назначении значения перечисления, которое не соответствует битовому полю.