问题描述
C++14 通过为值键入 0b
前缀来增加使用二进制文字的能力:
C++14 adds ability to use binary literals by typing 0b
prefix for the value:
int v = 0b1111; // 15 in decimal
但是对于 std::hex
或 std::oct
等流没有 std::bin
操纵器.所以我需要使用例如std::bitset
用于打印目的:
But there is no std::bin
manipulator for streams like std::hex
or std::oct
. So I need to use e.g. std::bitset
for printing purpose:
std::cout << std::bitset<4>(v) << "
";
是否已提出或考虑过?如果有,这个想法的状态如何?
Has it been proposed or considered? If so, what's the status of the idea?
推荐答案
据我所知,没有提交添加格式化标志以添加二进制格式和/或操纵器的建议std::bin代码>.您可以在 http://www.open-std 查看提案.org/jtc1/sc22/wg21/docs/papers/.我很确定添加二进制文字的提议没有添加此功能(快速搜索显示 N3472 但我不确定这是否是论文的最新版本.
As far as I know there was no proposal submitted to add a formatting flag to add binary formatting and/or a manipulator std::bin
. You can check the proposals at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/. I'm pretty sure the proposal to add binary literals did not add this facility (a quick search revealed N3472 but I'm not sure if this is the latest version of the paper).
从技术角度来看,添加可能并不容易!各种标志通常都存储在流类中的一个字中,并且有各种原因会用完所有位.现有的三个设置(std::ios_base::oct
、std::ios_base::dec
、std::ios_base::hex
)可以很好地存储在 2 位中.当然,这三个值会留下一个值,除了这个值通常用于默认设置,即读取时不固定底座.因此,可能需要更改流类的布局或降低处理效率(例如,通过某种方式使用 iword()
来存储二进制格式的额外可能性).我还没有分析任何实现是否存在实际问题(我知道我的实现没有问题,但如果我没记错的话,我确实使用了单词中的所有位).
From a technical point of view it may not be entirely easy to add! The various flags are normally all stored in just one word in the stream class and there are various reasons to use up all the bits. The existing three settings (std::ios_base::oct
, std::ios_base::dec
, std::ios_base::hex
) can be nicely stored in just 2 bits. Of course, the three values would leave one value open except that this value is typically taken for the default setting, i.e., not fixing the base when reading. As a result it may be necessary to change the layout of the stream classes or to make processing less efficient (e.g., by somehow using an iword()
to store the additional possibility of binary formatting). I haven't done the analysis whether there is an actual problem with any of the implementations (I know there is none for my implementation but I did use all the bits in a word if I recall correctly).
如果您想支持二进制格式,通过自定义 std::num_put<char>
facet 添加相对容易.下面是一个简单的例子.它不处理一些可能需要的格式选项,例如填充或数字分隔符:
If you want to support binary formatting it is relatively easy to add via a custom std::num_put<char>
facet. Below is a simple example. It doesn't deal with some of the formatting options which may be desirable like padding or digit separators:
#include <iostream>
#include <limits>
#include <locale>
class binary_num_put
: public std::num_put<char> {
template <typename T>
iter_type common_put(iter_type out, std::ios_base& str, char_type fill,
T original, unsigned long long v) const {
if (str.flags() & std::ios_base::basefield) {
return this->std::num_put<char>::do_put(out, str, fill, original);
}
if (str.flags() & std::ios_base::showbase) {
*out++ = '0';
*out++ = str.flags() & std::ios_base::uppercase? 'B': 'b';
}
unsigned long long mask(1ull << (std::numeric_limits<unsigned long long>::digits - 1));
while (mask && !(mask & v)) {
mask >>= 1;
}
if (mask) {
for (; mask; mask >>= 1) {
*out++ = v & mask? '1': '0';
}
}
else {
*out++ = '0';
}
return out;
}
iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long v) const {
return common_put(out, str, fill, v, static_cast<unsigned long>(v));
}
iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long long v) const {
return common_put(out, str, fill, v, static_cast<unsigned long long>(v));
}
iter_type do_put(iter_type out, std::ios_base& str, char_type fill, unsigned long v) const {
return common_put(out, str, fill, v, v);
}
iter_type do_put(iter_type out, std::ios_base& str, char_type fill, unsigned long long v) const {
return common_put(out, str, fill, v, v);
}
};
std::ostream& bin(std::ostream& out) {
auto const& facet = std::use_facet<std::num_get<char>>(out.getloc());
if (!dynamic_cast<binary_num_put const*>(&facet)) {
std::locale loc(std::locale(), new binary_num_put);
out.imbue(loc);
}
out.setf(std::ios_base::fmtflags(), std::ios_base::basefield);
return out;
}
int main()
{
std::cout << std::showbase << bin << 12345 << " "
<< std::dec << 12345 << "
";
}
这篇关于是否有提议将 std::bin 添加到 c++ 标准?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!