我可以从 uint8_t(或 std::byte)范围初始化 std::vector<bool>,以便输入中的每一位都被视为布尔值吗?
Can I initialize a std::vector<bool> from uint8_t (or std::byte) range so that every bit in input is treated as a boolean?
我知道 std::vector<bool>
is bad,但我有一个非常好的用例。
我想做这样的事情:
uint8_t data [] = {7,32};
std::vector<bool> vb/*...*/ ;
// now vb is size of 8 vector with this values:
// false, false, false, false, false, true, true, true, (7)
// false, false, true, false, false, false, false, false (32)
注意:我知道我可以手动分解输入的每个字节并进行 8 次插入,但我正在寻找标准中预构建的东西
std::vector<bool>
在这里是一个糟糕的选择,因为您正在考虑它的实现而不是它的行为....只是避免 vector<bool>
.
改用 boost::dynamic_bitset
。有趣的是,我个人发现它的性能要好得多:
std::array<std::uint8_t, 2> data {7,32};
boost::dynamic_bitset<std::uint8_t> vb(rbegin(data), rend(data));
std::cout << vb; // 0000011100100000
Live Demo
我们必须反转输入范围,因为 boost 的动态位集 appends 到最高有效位所在的末尾(通常是左侧),而不是右侧。
对此的建议是 P0237 基本位操作的措辞
公用事业:
#include <bit>
#include <cstdint>
std::uint8_t data [] = {7,32};
std::vector<bool> vb(
std::bit_iterator(std::begin(data), 0)),
std::bit_iterator(std::end(data), 0)));
使用 boost 容器无疑是最好的方法 - 但如果这不是一个选项,您可以创建一个迭代器类型来直接在构建时填充 vector<bool>
。
示例:
struct biterator {
using value_type = bool;
using reference = bool;
using difference_type = std::ptrdiff_t;
using pointer = uint8_t*;
using iterator_category = std::forward_iterator_tag;
biterator(const uint8_t* c) : curr(c), bit(1U<<7) {}
biterator& operator++() { if(!(bit >>= 1)) { ++curr; bit = 1U<<7; } return *this; }
bool operator*() const { return *curr & bit; }
bool operator!=(const biterator& rhs) const { return curr != rhs.curr; }
private:
const uint8_t* curr;
uint8_t bit;
};
用法:
uint8_t data [] = {7, 32};
std::vector<bool> vb(biterator(std::begin(data)), biterator(std::end(data)));
我知道 std::vector<bool>
is bad,但我有一个非常好的用例。
我想做这样的事情:
uint8_t data [] = {7,32};
std::vector<bool> vb/*...*/ ;
// now vb is size of 8 vector with this values:
// false, false, false, false, false, true, true, true, (7)
// false, false, true, false, false, false, false, false (32)
注意:我知道我可以手动分解输入的每个字节并进行 8 次插入,但我正在寻找标准中预构建的东西
std::vector<bool>
在这里是一个糟糕的选择,因为您正在考虑它的实现而不是它的行为....只是避免 vector<bool>
.
改用 boost::dynamic_bitset
。有趣的是,我个人发现它的性能要好得多:
std::array<std::uint8_t, 2> data {7,32};
boost::dynamic_bitset<std::uint8_t> vb(rbegin(data), rend(data));
std::cout << vb; // 0000011100100000
Live Demo
我们必须反转输入范围,因为 boost 的动态位集 appends 到最高有效位所在的末尾(通常是左侧),而不是右侧。
对此的建议是 P0237 基本位操作的措辞 公用事业:
#include <bit>
#include <cstdint>
std::uint8_t data [] = {7,32};
std::vector<bool> vb(
std::bit_iterator(std::begin(data), 0)),
std::bit_iterator(std::end(data), 0)));
使用 boost 容器无疑是最好的方法 - 但如果这不是一个选项,您可以创建一个迭代器类型来直接在构建时填充 vector<bool>
。
示例:
struct biterator {
using value_type = bool;
using reference = bool;
using difference_type = std::ptrdiff_t;
using pointer = uint8_t*;
using iterator_category = std::forward_iterator_tag;
biterator(const uint8_t* c) : curr(c), bit(1U<<7) {}
biterator& operator++() { if(!(bit >>= 1)) { ++curr; bit = 1U<<7; } return *this; }
bool operator*() const { return *curr & bit; }
bool operator!=(const biterator& rhs) const { return curr != rhs.curr; }
private:
const uint8_t* curr;
uint8_t bit;
};
用法:
uint8_t data [] = {7, 32};
std::vector<bool> vb(biterator(std::begin(data)), biterator(std::end(data)));