为非数组元素重载下标运算符 [英] Overloading subscript operator for non-array elements
问题描述
我写了一个模板类来存储多个bool在一个整数。
现在,设置和获取每个bool是用显式函数完成的
bool isBitSet(int index)
{
return static_cast< bool>((block_>> index)%2)
}
void setBitOn(int index)
{
block_ | = 1<<指数;
}
我相信下面的方法可以获得一个值,因为我们不能直接返回一个引用。
const bool operator [](int index)const
{
return static_cast< bool>((block_>>> index)%2);
}
code> std :: vector< bool> 和在 std :: bitset
如参考中所述, std :: vector< bool>
它返回一个代理类,它的运算符重载,作为向量的一个元素。
你也可以这样做。
对于用户友好的示例,请再次查看引用为公共接口,它是这样的:
template< class Allocator> ;
class vector< bool,Allocator> {
// ...
public:
类引用{
friend class vector;
reference();
public:
〜reference();
operator bool()const;
reference& operator =(bool x);
reference& operator =(const reference&);
void flip();
};
// ...
};
要实现这个类,你应该存储一个成员指针指向你的实际数据块, 。
对于一个真实的例子,在g ++头文件中查找 std :: vector< bool>
在文件 bits / stl_bvector.h
中调用 std :: vector< bool> :: Bit_reference
以一个例子来说明OP:
类包含320 bools。你可以写成:
class boolcontainer {
uint32_t data [10]
public:
//默认ctor。以便用零初始化元素
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&你需要添加一些操作符,即转换为bool和operator =:
类引用{
uint32_t * dataptr;
uint32_t mask;
public:
//构造函数只是初始化成员
引用(uint32_t * dataptr_,uint32_t mask_):dataptr(dataptr_),mask(mask_){}
/ /转换为bool
operator bool()const {
//就像在getter中一样,但是位掩码存储在本地
return * dataptr&面具;
}
//将由mask表示的一个位设置为b
reference& operator =(bool b){
if(b){
* dataptr | = mask;
} else {
* dataptr& =〜mask;
}
return * this;
}
// TODO copy ctor。,operator ==,operator<
};
请注意,上述结构将表现为bool& - 从其读取从指针和掩码表示的数据点读取值,并且类似地,写入它覆盖所表示位置处的位。我还写了一个初始化成员的构造函数。
现在你需要的是你的boolcontainer的operator []应该返回一个上面类的对象:
class boolcontainer {
uint32_t data [10];
public:
boolcontainer(){for(int i = 0; i <10; ++ i){data [i] = 0; }}
类引用{
... //见上面的
}
//保持效率的const版本
bool operator [](int i)const {return data [i / 32]& (1 <(i%32)); }
//非const版本返回我们的引用对象。
reference operator [](int i){return reference(& data [i / 32],1 < }
};
现在一些代码测试它(仅打印前40个值):
#include< iostream>
#includeboolcontainer.h
void printboolcontainer(const boolcontainer& bc)
{
//注意这是常量版本
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);
}
I have written a templates class for storing multiple bools in an integer. Right now, setting and getting each bool is done with explicit functions
bool isBitSet(int index)
{
return static_cast<bool>((block_ >> index) % 2)
}
void setBitOn(int index)
{
block_ |= 1 << index;
}
I believe that the following would work for getting a value, but how would setting work since we can't directly return a reference for a bit?
const bool operator [] (int index) const
{
return static_cast<bool>((block_ >> index) % 2);
}
The same is done in std::vector<bool>
and in std::bitset
in the standard library. As stated in the reference, std::vector<bool>
it returns a proxy class that has its operators overloaded to act as an element of the vector.
You could to that as well.
For a user-friendly example see again the reference for a public interface, it is something like this:
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();
};
// ...
};
To implement this class you should store a member pointer to your actual data block and a mask to operate with.
For a real example, in the g++ headers look for member class of std::vector<bool>
called std::vector<bool>::_Bit_reference
in the file bits/stl_bvector.h
.
To clarify the OP with an example:
Let's say you have a class containing 320 bools. You could write it as:
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; } }
}
You want to add an operator[]. To add a const one is easy:
class boolcontainer {
uint32_t data[10];
public:
bool operator[](int i) const { return data[i/32] & (1 << (i%32)); }
}
to have a non-const one you need much more. First you need to create a class that represents a reference to your value. You must have some kind of pointer to where the value is stored and (in this case) you need a bitmask to specify one concrete bit. To be able to handle this as a bool& you need to add some operators, namely conversion to bool and 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<
};
Note that the above struct will behave as a bool& -- reading from it reads the value from the data point represented by the pointer and the mask, and similarly, writing to it overwrites the bit at the represented location. I also wrote a constructor that initializes the members.
Now all you need is that your boolcontainer's operator[] should return an object of the above class:
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)); }
};
And now some code to test it (prints only the first 40 values):
#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);
}
这篇关于为非数组元素重载下标运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!