我编写了一个模板类,用于在整数中存储多个bool。 现在,设置和获取每个bool都是通过显式函数完成的
bool isBitSet(int index)
{
return static_cast<bool>((block_ >> index) % 2)
}
void setBitOn(int index)
{
block_ |= 1 << index;
}
我相信以下内容对于获取值有用,但是如果设置工作,我们不能直接返回一个引用?
const bool operator [] (int index) const
{
return static_cast<bool>((block_ >> index) % 2);
}
答案 0 :(得分:6)
标准库中的std::vector<bool>
和std::bitset
也是如此。如reference中所述,std::vector<bool>
它返回一个代理类,该代理类将其运算符重载以充当向量的元素。
你也可以这样做。
对于用户友好的示例,请再次查看公共接口的reference,它是这样的:
template <class Allocator>
class vector<bool, Allocator> {
// ...
public:
class reference {
friend class vector;
reference();
public:
~reference();
operator bool() const;
reference& operator=(bool x);
reference& operator=(const reference&);
void flip();
};
// ...
};
要实现此类,您应该存储一个指向实际数据块的成员指针和一个用于操作的掩码。
对于一个真实的例子,在g ++标题中查找文件std::vector<bool>
中名为std::vector<bool>::_Bit_reference
的成员类bits/stl_bvector.h
。
用一个例子澄清OP:
假设您有一个包含320个bool的类。你可以把它写成:
class boolcontainer {
uint32_t data[10];
public:
//default ctor. to initialize the elements with zeros
boolcontainer() { for (int i = 0; i < 10; ++i) { data[i] = 0; } }
}
您想要添加运算符[]。添加一个const很容易:
class boolcontainer {
uint32_t data[10];
public:
bool operator[](int i) const { return data[i/32] & (1 << (i%32)); }
}
要有一个非常规的,你需要更多。首先,您需要创建一个表示对您的值的引用的类。你必须有一些指向存储值的指针(在这种情况下)你需要一个位掩码来指定一个具体的位。为了能够将其作为一个bool&amp;你需要添加一些运算符,即转换为bool和operator =:
class reference {
uint32_t *dataptr;
uint32_t mask;
public:
//constructor just initializing members
reference(uint32_t *dataptr_, uint32_t mask_) : dataptr(dataptr_), mask(mask_) {}
//conversion to bool
operator bool() const {
//just like in the getter, but the bitmask is stored now locally
return *dataptr & mask;
}
//sets one single bit represented by mask to b
reference& operator=(bool b) {
if (b) {
*dataptr |= mask;
} else {
*dataptr &= ~mask;
}
return *this;
}
//TODO copy ctor., operator==, operator<
};
请注意,上面的结构将表现为bool&amp; - 从中读取读取指针和掩码所代表的数据点的值,类似地,写入它会覆盖所代表位置的位。我还写了一个初始化成员的构造函数。
现在您需要的是您的boolcontainer的operator []应该返回上述类的对象:
class boolcontainer {
uint32_t data[10];
public:
boolcontainer() { for (int i = 0; i < 10; ++i) { data[i] = 0; } }
class reference {
... //see above
}
//keep the const version for efficiency
bool operator[](int i) const { return data[i/32] & (1 << (i%32)); }
//non-const version returns our reference object.
reference operator[](int i) { return reference(&data[i/32], 1 << (i%32)); }
};
现在有一些代码来测试它(只打印前40个值):
#include <iostream>
#include "boolcontainer.h"
void printboolcontainer(const boolcontainer &bc)
{
//note that this is the constant version
for (int i = 0; i < 40; ++i) {
std::cout << bc[i];
}
std::cout << std::endl;
}
int main()
{
boolcontainer bc;
printboolcontainer(bc);
bc[0] = true;
bc[3] = true;
bc[39] = true;
printboolcontainer(bc);
}