同じことが instd::vector<bool>
および instd::bitset
標準ライブラリで行われます。リファレンスに記載されているようstd::vector<bool>
に、ベクトルの要素として機能するように演算子がオーバーロードされたプロキシ クラスを返します。
あなたもそれをすることができます。
ユーザーフレンドリーな例については、パブリック インターフェイスのリファレンスをもう一度参照してください。これは次のようなものです。
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>
calledのメンバー クラスを探します。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; } }
}
operator[] を追加します。const を追加するのは簡単です:
class boolcontainer {
uint32_t data[10];
public:
bool operator[](int i) const { return data[i/32] & (1 << (i%32)); }
}
const 以外のものを使用するには、さらに多くのものが必要です。まず、値への参照を表すクラスを作成する必要があります。値が格納されている場所へのある種のポインターが必要であり、(この場合) 1 つの具体的なビットを指定するためのビットマスクが必要です。これを bool& として処理できるようにするには、いくつかの演算子、つまり 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& として動作することに注意してください。それを読み取ると、ポインターとマスクによって表されるデータ ポイントから値が読み取られ、同様に、それに書き込むと、表された位置のビットが上書きされます。メンバーを初期化するコンストラクターも作成しました。
ここで必要なのは、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);
}