【发布时间】:2021-05-28 16:03:00
【问题描述】:
在 range-based-for 中循环 std::vector<bool> 以更改数据,需要使用 转发引用 或仅使用 值类型 :
std::vector<bool> bv(5);
bool val = true;
for(auto&& b : bv) {
b = val;
val = !val;
}
或者:
std::vector<bool> bv(5);
bool val = true;
for(auto b : bv) {
b = val; // yes, this alters the vector
val = !val;
}
但这不起作用:
std::vector<bool> bv(5);
bool val = true;
for(auto& b : bv) {
// ...
}
上面的结果与已知的编译错误:
cannot bind non-const lvalue reference of type 'std::_Bit_reference&'
to an rvalue of type 'std::_Bit_iterator::reference'
9 | for(auto& b : bv) {
| ^~
问题是,理论上和实践上,std::vector<bool> 是否可以为其迭代器实现 operator*,以返回 引用 到 Bit_reference? p>
在实现一个简单的 BoolArray 版本并且能够循环引用我的内部 BoolProxy 时,我想到了这个问题:
template<size_t SIZE>
class BoolArray {
public:
// forward declaration
class iterator;
private:
char arr[(SIZE-1)/8 + 1] = {};
class BoolProxy {
char* const arr;
size_t index;
size_t byte_index() const {
return index / 8;
}
size_t bit_index() const {
return index % 8;
}
char bit_val() const {
return 1 << bit_index();
}
public:
friend class BoolArray<SIZE>::iterator;
BoolProxy(char* const arr, size_t index): arr(arr), index(index) {}
operator bool() const {
return arr[byte_index()] & bit_val();
}
bool operator=(bool value) {
if(value) {
arr[byte_index()] |= bit_val();
}
else {
arr[byte_index()] &= ~(bit_val());
}
return value;
}
};
public:
class iterator {
BoolProxy bp;
public:
iterator(BoolProxy bp): bp(bp) {}
iterator& operator++() {
++bp.index;
return *this;
}
bool operator*() const {
return bp;
}
// we return here a BoolProxy byref!
// is there something wrong with it?
auto& operator*() {
return bp;
}
bool operator!=(iterator other) {
return bp.arr != other.bp.arr || bp.index != other.bp.index;
}
};
auto begin() {
return iterator{BoolProxy{arr, 0}};
}
auto end() {
return iterator{BoolProxy{arr, SIZE}};
}
};
int main() {
BoolArray<5> barr;
bool val = true;
for(auto& b : barr) { // looping on a reference here
b = val;
val = !val;
}
for(auto b : barr) {
std::cout << b << ' ';
}
}
迭代器确实作为右值返回,但在基于范围的范围内,它的生命周期将被延长,这应该允许从中获取对其内部 BoolProxy 的引用。
【问题讨论】:
-
auto& bit_ref = *it; it++;和bit_ref被修改,不是很直观。 -
@Amir: "需要使用转发引用或只使用值类型" 你应该get used to using
auto&&in range code。