字节到位运算符重载C++
Byte to bits Operator Overloading C++
我写C++已经很长时间了,也许是因为我不需要经常这样做,但我似乎在运算符重载方面有所欠缺。我不时地使用它,但从未需要做我最近想做的事情,并发现它有点问题。
class foo
{
public:
static const size_t ARRAY_SIZE = 100000;
uint8_t& operator[](const size_t& index) { return my_array[index >> 3]; }
// problematic equality operator
bool operator==(const size_t& index) const { return my_array[index >> 3] & (1 << (index & 7)); }
//
// Need an assignment operator to do:
// my_array[index >> 3] |= 1 << (index & 7);
// ^------------------^ might not needed as it's returned from [] operator
private:
std::array<uint8_t, (ARRAY_SIZE >> 3) + ((ARRAY_SIZE & 7) ? 1 : 0)> my_array;
};
从上面可以看出,这里要做的是获取一个size_t数字,并将其存储在它的相对位位置。因此,例如,5将存储在数组等中字节0的比特4中,9将存储在字节1的比特1中。
现在,下标运算符工作正常,并从数组中返回正确的字节,但这留下了这样的问题:
if (foo[n]) // where n is a size_t integer representing a bit position
然后我意识到,以上是的缩写形式
if (foo[n] == true)
因此,我编写了上面的等式运算符,但由于某种原因,我不明白,运算符没有被调用。我以为它会在下标运算符之后被调用,还是因为它不再是foo类型的对象而没有被调用?解决这个问题的最佳方法是什么?是写一个外部运算符==并使其成为foo的朋友吗?
哦,还有一些关于赋值运算符构造的建议也将不胜感激。非常感谢。。。
编辑:感谢所有人的帮助。我确实认为,因为问了一个我不太理解的问题而被否决是非常残酷的。这并不是一个愚蠢的问题,如果你仔细阅读我最初的问题,我确实质疑foo可能不是下标运算符后面的正确类型,正如你们中的一些人所指出的那样。无论如何,这里有更多的上下文。我还没有机会好好研究所有很棒的回复。。。
我最初写的操作符是这样的,它实际上从数组中返回了正确的位。有些人已经指出了。
bool operator[](const size_t index) const { return my_array[index >> 3] & (1 << (index & 7)); }
然后我遇到的问题是设置阵列中的位:
foo f;
if (f[3]) // this is fine
但做一些类似的事情:
f[6] = true;
我想我所希望的是一种比写以下内容更优雅的方式:-
class Foo
{
public:
static const size_t MAX_LIST_SIZE = 100000;
bool get(const size_t index) const { return my_array[index >> 3] & (1 << (index & 7)); }
void set(const size_t index) { my_array[index >> 3] |= 1 << (index & 7); }
private:
std::array<uint8_t, ((MAX_LIST_SIZE >> 3) + ((MAX_LIST_SIZE & 7) ? 1 : 0))> my_array;
}
然后使用这样的类:
Foo f
f.set(10);
if (f.get(10))
...
我只是觉得操作人员过载会更容易,但从外观上看,它似乎更麻烦。(哦,有人问我为什么用uint8_t而不是bool,这是因为在这个特定的平台上,bool实际上是32位!)
这里我们有几个深刻的误解。
现在下标运算符工作正常并返回正确的字节来自数组,但这留下了这样的问题:
if (foo[n]) // where n is a size_t integer representing a bit position
您的问题不是if
本身;这是因为你归还的东西不对。如果您正在构建一个压缩比特集,那么operator[]
应该只返回请求位置的比特值。因此:
bool operator[](size_t index) { return (my_array[index >> 3]) & (1<<(index&7)); }
在这里,您的if
以及涉及operator[]
的任何其他操作都将按预期工作。
然后我意识到上面是的缩写形式
if (foo[n] == true)
不是。if
计算括号内的表达式,并(本质上)将其强制转换为布尔值;如果结果为true
,则执行分支,否则不执行。
,因此我编写了上面的等式运算符,但由于某种原因我不理解,该运算符没有被调用。
未调用运算符,因为:
- 如上所述,
operator==
从不涉及if (foo[n])
- 即使显式编写了
if (foo[n]==true)
,也不会调用您的运算符,因为一旦返回operator[]
,就不再涉及foo
想想看:即使在你的"原始的";operator[]
返回对uint8_t
的引用。声明:
if (a[n] == true)
(a
为foo
型)
实际上与相同
uint8_t &temp = a[n];
if (temp == true)
现在,在表达式temp == true
中,a
的类型从未被提及——只有temp
,它是uint8_t&
,与它是如何获得的无关,还有true
,它是一个bool
文字。如果您将a
与size_t
进行比较,则会考虑您的operator==
,但这毫无意义。
最后,关于您的评论:
// Need an assignment operator to do: // my_array[index >> 3] |= 1 << (index & 7); // ^------------------^ might not needed as it's returned from [] operator
同样,由于完全相同的原因,这将不起作用-您需要一个运算符重载来处理operator[]
的返回值,而不是foo
类本身。
这通常是通过让operator[]
返回的不是值本身,而是一个代理对象来实现的,该代理对象记住其父对象和请求的索引,并提供自己的operator==
和operator=
来执行您试图在foo
类中直接输入的内容(以及使其可以传递对布尔值的引用的额外运算符)。
类似于:
struct PackedBitVector {
static const size_t ARRAY_SIZE = 100000;
struct ElementProxy {
PackedBitVector &parent;
size_t idx;
operator bool() const { return parent.data[idx>>3] & (1<<(idx&7)) }
bool operator==(bool other) const { return bool(*this) == other; }
bool operator!=(bool other) const { return !(*this == other); }
ElementProxy &operator=(bool other) {
if(other) parent.data[idx>>3] |= 1<<(idx&7);
else parent.data[idx>>3] &= ~(1<<(idx&7));
return *this;
}
}:
ElementProxy operator[](size_t index) { return ElementProxy{*this, index}; }
private:
std::array<uint8_t, (ARRAY_SIZE >> 3) + ((ARRAY_SIZE & 7) ? 1 : 0)> data;
};
要使其正常工作,您必须添加一个完整的其他操作符桶,以便该代理对象可以可靠地作为对bool
的引用传递,std::vector<bool>
就是这样做的。
关于这一点,从你关于bool
在你的平台上是32位宽的评论中,你似乎不知道std::vector<bool>
已经在运动了;压缩位阵列";空间优化,因此您可以直接使用它,而无需重新实现真实事物的损坏版本。
- 继承函数的重载解析
- 你能重载对象变量名本身返回的内容吗
- 从父命名空间重载类型
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 重载操作程序时出错>>用于类中的字符串 memebr
- 一个关于在C++中重载布尔运算符的问题
- 不同翻译单元中不可重载的非内联函数定义
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 将重载的成员函数传递给函数模板
- c++:可变模板和函数重载
- 重载元组索引运算符-C++
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 重载==不适用于二进制树
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 重载运算符new[]的行为取决于析构函数
- 正在尝试重载二进制搜索树分配运算符
- 重载Singly Linked List中的赋值运算符
- 取消引用运算符不能重载