Почему std::setbase(2) не переключается на двоичный вывод?
Страница CPPReference на std::setbase говорит:
Значения базы, отличные от 8, 10 или 16, сбрасывают базовое поле на ноль, что соответствует десятичному выводу и вводу, зависящему от префикса.
Как так?
Есть ли конкретная причина, по которой поддерживаются только эти базы? Кажется тривиальным поддерживать хотя бы что-нибудь до 16 (на самом деле, до 36: 0-9 и затем az) без необходимости делать какие-либо трудные выборы. В частности, 2 является популярной базой, я думаю, что должен быть интерес к std::setbase(2)
(и соответствующий std::binary
).
Я, очевидно, могу напечатать свои собственные биты, но для моего ostream было бы хорошо сделать это.
2 ответа
Единственный верный ответ - "потому что так говорится в стандарте".
При этом стандарт в основном формализовал предстандартные реализации iostream, многие из которых, вероятно, были разработаны просто для достижения функционального равенства с printf
, который поддерживает только десятичные, восьмеричные и шестнадцатеричные (через специальный, не очень общий синтаксис).
Кроме того, как и сейчас, было бы несложно исправить API-интерфейс iostream для поддержки "многих" баз, учитывая, что базовая настройка заканчивается битовым полем, а не отдельным полем "текущей базы".
Теперь стандарт требует fmtflags
иметь некоторый "тип битовой маски" - который может даже быть std::bitset
Таким образом, вы можете найти способ как-то перелопачивать все эти новые "базовые" поля - но действительно ли это стоит усилий (плюс риск взлома кода, который предполагает, что fmtflags
является интегральным типом) для функции, которая практически никого не волнует?
Итак, подведем итог: плохой первоначальный дизайн (как, впрочем, и остальная часть iostream), нетривиальное исправление и отсутствие реальной потребности пользователя в такой функции.
Насколько мне известно, предложения о добавлении поддержки двоичного (base 2) форматирования в iostreams (см. Также не поступалоБыло ли предложение добавить std ::bin в стандарт C ++? ). Однако он поддерживается в C++20.:
std::string s = std::format("{:b}", 42);
не является широко доступным, но вы можете использовать библиотеку {fmt} , основанную на:
std::string s = fmt::format("{:b}", 42);
Отказ от ответственности : я являюсь автором {fmt} и C++20
std::format
.