Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't std::setbase(2) switch to binary output?

The cppreference page on std::setbase says:

Values of base other than 8, 10, or 16 reset basefield to zero, which corresponds to decimal output and prefix-dependent input.

How come?

Is there a particular reason why only these bases are supported? It seems trivial to support at least anything up to 16 (actually, up to 36: 0-9 and then a-z) without having to make any sort of difficult choices. Specifically, 2 is a popular base, I would think there should be interest in std::setbase(2) (and a corresponding std::binary).

I can obviously print my own bits but it would have been nice for my ostream to do it.

like image 965
einpoklum Avatar asked Apr 18 '16 19:04

einpoklum


2 Answers

The only sure answer is "because the standard says so".

That being said, the standard mostly formalized the pre-standard iostream implementations, many of which probably were designed just to reach feature parity with printf, which supports only decimal, octal and hexadecimal (through ad-hoc, not-really-general syntax).

Also, as it is now it wouldn't be trivial to patch the iostream API to support "many" bases, given that the base setting ends up into a bitfield, not in a separate "current base" field.

Now, the standard requires fmtflags to be of some "bitmask type" - which may even be a std::bitset, so you may find a way to shovel all those new "base" fields somehow - but is it really worth the effort (plus the risk of breaking the code that assumes that fmtflags is of an integral type) for a feature that almost nobody really cares about?

So, to sum it up: bad initial design (like the rest of iostream, actually), nontrivial fix and no real user demand for such a feature.

like image 197
Matteo Italia Avatar answered Oct 21 '22 07:10

Matteo Italia


To the best of my knowledge there was no proposal to add support for binary (base 2) formatting to iostreams (see also Has there been a proposal to add std::bin to the c++ standard?). However, it is supported in C++20 std::format:

std::string s = std::format("{:b}", 42);

std::format is not widely available but you can use the {fmt} library, std::format is based on, in the meantime:

std::string s = fmt::format("{:b}", 42);

Disclaimer: I'm the author of {fmt} and C++20 std::format.

like image 5
vitaut Avatar answered Oct 21 '22 08:10

vitaut