C++11 и [17.5.2.1.3] типы битовых масок
Стандарт позволяет выбирать между целочисленным типом, enum
и std::bitset
,
Почему разработчик библиотеки использует один над другим, учитывая эти выборы?
В данном случае libcxx от llvm, по-видимому, использует комбинацию (как минимум) двух из этих вариантов реализации:
ctype_base::mask
реализован с использованием целочисленного типа: <__locale>
regex_constants::syntax_option_type
реализуется с использованием enum
+ перегруженные операторы: <regex>
LibstdC++ проекта gcc использует все три:
ios_base::fmtflags
реализовано с использованием enum + перегруженных операторов: <bits/ios_base.h>
regex_constants::syntax_option_type
реализуется с использованием целочисленного типа, regex_constants::match_flag_type
реализуется с помощью std::bitset
И то и другое: <bits/regex_constants.h>
AFAIK, GDB не может "обнаружить" битовую поля любого из этих трех вариантов, поэтому не будет никакой разницы по сравнению с улучшенной отладкой.
enum
Решение и решение целочисленного типа всегда должны использовать одно и то же пространство. std::bitset
кажется, не дает гарантии того, что sizeof(std::bitset<32>) == std::uint32_t
так что я не понимаю, что особенно привлекательно std::bitset
,
enum
Решение кажется немного менее безопасным, потому что комбинации масок не генерируют перечислитель.
Строго говоря, вышеупомянутое относится к n3376, а не к FDIS (поскольку у меня нет доступа к FDIS).
Любое доступное просвещение в этой области будет оценено.
3 ответа
Удивительно то, что стандарт ограничивает его тремя вариантами. Почему тип класса не должен быть приемлемым? Тем не мение…
- Интегральные типы являются простейшей альтернативой, но им не хватает безопасности типов. Очень старый унаследованный код будет использовать их, так как они также являются самыми старыми.
- Типы перечисления безопасны, но громоздки, и до C++11 они, как правило, фиксировались на размер и диапазон
int
, std::bitset
может быть иметь несколько больше безопасности типа в этомbitset<5>
а такжеbitset<6>
Это разные типы, и добавление запрещено, но в остальном небезопасно, как целочисленный тип. Это не было бы проблемой, если бы они допускали типы, полученные изstd::bitset<N>
,
очевидно enum
Это идеальная альтернатива, но опыт доказал, что безопасность типов действительно не нужна. Таким образом, они бросили реализаторам кость и позволили им выбрать более легкий путь. Короткий ответ, то, что лень заставляет разработчиков выбирать int
или же bitset
,
Немного странно, что типы, полученные из bitset
не допускаются, но на самом деле это мелочь
Основная спецификация, представленная в этом разделе, представляет собой набор операций, определенных для этих типов (т. Е. Побитовых операторов).
Я предпочитаю использовать enum, но иногда есть веские причины использовать целое число. Обычно ctype_base::mask
взаимодействует с собственными заголовками ОС, с отображением из ctype_base::mask
к <ctype.h>
константы, определяемые реализацией, такие как _CTYPE_L
а также _CTYPE_U
используется для isupper
а также islower
и т. д. Использование целого числа может упростить использование ctype_base::mask непосредственно с нативными API-интерфейсами ОС.
Я не знаю, почему libstdC++ <regex>
использует std::bitset
, Когда этот код был зафиксирован, я сделал пометку, чтобы заменить целочисленные типы перечислением в некоторый момент, но <regex>
для меня не является приоритетом.
Почему стандарт допускает различные способы реализации библиотеки? И ответ: почему бы и нет?
Как вы видели, все три варианта, очевидно, используются в некоторых реализациях. Стандарт не хочет делать существующие реализации несоответствующими, если этого можно избежать.
Одной из причин использования набора битов может быть то, что его размер подходит лучше, чем перечисление или целое число. Не все системы даже имеют std::uint32_t
, Может быть bitset<24>
там лучше будет работать?