3

複数のブール値を整数に格納するためのテンプレート クラスを作成しました。現在、各ブール値の設定と取得は明示的な関数で行われます

    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);
    }
4

1 に答える 1

6

同じことが 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_referencebits/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);
}
于 2013-02-11T07:58:08.057 に答える