Бит-поля "Инициализация внутри класса" приводит к "ошибке: lvalue, требуемой как левый операнд назначения", - программирование

Бит-поля "Инициализация внутри класса" приводит к "ошибке: lvalue, требуемой как левый операнд назначения",

struct bitfield {
  int i = 0;  // ok
  int j : 8 = 0;  // error: lvalue required as left operand of assignment
};

Каков правильный синтаксис для инициализации битовых полей с использованием функции инициализации С++ 11 "внутри класса"?

4b9b3361

Ответ 1

Каков правильный синтаксис для инициализации битовых полей с использованием функции инициализации С++ 11 "внутри класса"?

Вы не можете инициализировать бит-поля в классе. Параграф 9.2 стандарта С++ 11 указывает грамматику для деклараторов членов класса:

[...]

член-описатель:

declarator virt-specifier-seq (opt) pure-specifier (opt)

     

declarator brace-or-equal-initializer (opt)

     

идентификатор (opt) attribute-specifier-seq (opt): константное выражение

Как вы можете видеть, деклараторы для элементов битового поля не могут быть прерваны с помощью инициализатора скобок или равного.

Ответ 2

Это было поднято как основной вопрос 1341 к стандарту С++, но было отклонено рабочей группой С++ Core в октябре 2015 года как NAD ( "не дефект" ) - см. http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1341

Ответ 3

Вы не можете (в С++ 11) инициализировать бит-поля в классе.

В MSVC и gcc (с расширениями) анонимный код union и struct позволяет немного обойти это.

struct bitfield {
  int i = 0;  // ok
  union {
    uint32_t raw = 0;
    struct {
      int j : 8;
      int x : 3;
    };
  };
};

где мы смешиваем фиксированный размер raw с union над битовыми полями, а затем в классе инициализируем элемент raw.

Ответ 4

Вы можете написать конструктор с именем инициализатора, чтобы указать значения по умолчанию для ваших битполей.

struct bitfield {
  int i;
  int j : 8;

  bitfield() : i(0), j(0) {};
};

Вы также можете создавать поля только для чтения со значениями по умолчанию.

struct _UserRegister1
{
  uint8_t _RES0 : 1;
  const uint8_t reserved1 : 1;
  uint8_t _HTRE : 1;
  const uint8_t reserved2 : 3;
  uint8_t _VDDS : 1;
  uint8_t _RES1 : 1;

  _UserRegister1() : reserved1(1), reserved2(7) {};
};