Ответ 1
Неконцевые ссылки не могут быть привязаны к битовым полям по той же причине, указатели не могут указывать на битовые поля.
Пока не указано, занимаются ли ссылки хранением, ясно, что в нетривиальных случаях они реализуются как маскирующие указатели, и эта реализация ссылок "предназначена" авторами языка. И точно так же, как указатели, ссылки должны указывать на адресный блок хранения. Невозможно связать неконстантную ссылку на блок хранения, который не адресуется. Поскольку ссылки, отличные от констант, требуют прямого связывания, ссылка не const может не привязываться к битовому полю.
Единственный способ создания указателя/ссылки, который может указывать на бит-поля, - это реализовать какой-то "суперпоинтер", который в дополнение к фактическому адресу в хранилище также будет содержать какой-то бит-смещение и бит- информацию о ширине, чтобы указать код записи, какие биты изменить. Обратите внимание, что эта дополнительная информация должна присутствовать во всех типах указателей данных, так как такого типа в С++ нет как "указатель/ссылка на бит-поле". Это в основном эквивалентно внедрению модели адресации хранилища более высокого уровня, полностью отделенной от модели адресации, предоставляемой базовой операционной системой/аппаратной платформой. Язык С++ никогда не предполагал, чтобы эта абстракция из базовой платформы не учитывала соображения чистой эффективности.
Одним жизнеспособным подходом было бы введение отдельной категории указателей/ссылок, таких как "указатель/ссылка на бит-поле", которая имела бы более сложную внутреннюю структуру, чем обычный указатель/ссылка на данные. Такие типы могут быть конвертированы из обычных указателей данных/ссылочных типов, но не наоборот. Но, похоже, это не стоит того.
В практических случаях, когда мне приходится иметь дело с данными, упакованными в биты и последовательности бит, я часто предпочитаю реализовывать бит-поля вручную и избегать битовых полей на уровне языка. Имя битового поля - это объект времени компиляции без возможности выбора времени выполнения. Когда требуется выбор времени выполнения, лучшим подходом является объявление обычного поля данных uint32_t
и управление отдельными битами и группами бит внутри него вручную. Выбор во время выполнения такого "битового поля" вручную может быть реализован с помощью масок и сдвигов (оба могут быть значениями времени выполнения). В принципе, это близко к ручной реализации вышеупомянутых "суперпоследователей".