我知道
std::vector<bool>
是 std::vector
的奇怪特化,除其他外,它的缺点是无法获取对单个元素的指针/引用。我遇到了一种情况,我需要指向元素的指针,由于额外的 deref,std::deque<bool>
并不理想,而 std::vector<unsigned char>
也不理想,因为我正在使用 std::anys,除非我完全承诺,否则它会向我大喊大叫永远不要将我的布尔值称为布尔值。由于输入“using Bool = unsigned char”对我来说太费力了,所以我决定创建一个帮助器类,它可以有效地充当指向 std::vector<bool>
: 元素的指针
//Vector Bool Pointer - Helper class used for getting/setting bools put into vectors using pointers
class VBP {
public:
VBP() {
ptr = nullptr;
mask = 0;
}
VBP(std::vector<bool>::reference ref) {
/*
std::vector<bool>::reference is the actual type returned when you index a
std::vector<bool>, it just has an implicit cast to bool:
constexpr operator bool() const noexcept {
return (*_Getptr() & _Mask()) != 0;
}
constexpr const _Vbase* _Getptr() const noexcept {
return this->_Myptr;
}
constexpr _Vbase _Mask() const noexcept {
return static_cast<_Vbase>(1) << this->_Myoff;
}
Since we can pass references around, we can store from them the necessary information
to effectively dereference them later.
*/
ptr = (unsigned*)ref._Getptr();
mask = static_cast<std::_Vbase>(1) << ref._Myoff; //I want to know whose idea it was to make
//_Mask() a protected function but leave _Myoff public.
}
VBP& operator=(const VBP& other) {
if (this != &other) {
this->ptr = other.ptr;
this->mask = other.mask;
}
return *this;
}
VBP& operator=(const bool& other) {
if (ptr != nullptr && (bool)(*ptr & mask) != other) {
*ptr ^= mask;
}
return *this;
}
bool operator==(const VBP& other) {
return this->ptr == other.ptr && this->mask == other.mask;
}
bool operator==(const bool& other) {
return ptr && (*ptr & mask) == other;
}
operator bool() {
return ptr && *ptr & mask;
}
bool operator !() {
return !ptr || !(*ptr & mask);
}
private:
unsigned* ptr;
std::_Vbase mask;
};
这个类有效,我个人对此没有任何问题,但我知道
std::vector<bool>
的工作方式取决于实现,所以我不确定我在这里所做的有多少可以在另一个上实现机器。例如,像 _Myoff 是公开的而 _Mask() 受到保护之类的东西似乎是一个奇怪的设计选择,我无法更广泛地依赖它。有没有办法实现指向 std::vector<bool>
元素的指针,无论如何实现它都可以工作?
std::vector<bool>::iterator
的语义与指向 bool
的指针非常接近,包括通过间接寻址为向量的元素分配新的 bool
值的能力。
这是一个说明这种方法的示例:
std::vector<bool> vb {true, true, false, false, true, false};
std::cout << vb.size() << std::endl;
for (size_t i = 0 ; i != vb.size() ; i++) {
std::vector<bool>::iterator ptr = std::next(vb.begin(), i);
std::cout << "before " << *ptr << " ";
*ptr = !(*ptr);
std::cout << "after " << *ptr << std::endl;
}
通过
*ptr
读取和通过 *ptr = ...
写入都按预期工作。