pigelin
pigelin

Reputation: 143

How to make operator[] return references to individual bits in unsigned int?

I'm making a vector<bool> implementation. I save an unsigned int and use bitwise operations to have a vector of true and false. My problem is this; I can access individual bits by operator[], but how do I get a reference to such a bit so I can write

Vector<bool> v(5, true);
v[3] = false;

Somewhere I heard that you shouldn't do references/pointers to individual bits. A summary of the code, that works for retrieving bit value:

...
unsigned int arr;       // Store bits as unsigned int
unsigned int size_vec;  // The size of "bool vector"
...

bool& Vector<bool>::operator[](unsigned int i) {
 if (i>=vec_size || i<0) {
    throw out_of_range("Vector<bool>::operator[]");
 }
 int index = 1 << (i-1);
 bool n = false;
 if (index & arr) {
     n=true;
 }
 return n;
};

So, how can you return some sort of reference making it possible to change the individual bits?

Upvotes: 0

Views: 213

Answers (4)

Peter Alexander
Peter Alexander

Reputation: 54270

You need to define a proxy object with the appropriate operator overloads so that it acts like bool& but addresses individual bits. This is what std::vector<bool> does.

Something like this:

struct Bit
{
public:
    typedef unsigned char byte;

    Bit(byte& _byte, byte _bit)
    : m_byte(_byte), m_mask(1u << _bit)
    {}

    operator bool() const
    {
        return m_byte & m_mask;
    }

    Bit& operator=(bool x)
    {
        m_byte = x ? m_byte | m_mask : m_byte & ~m_mask;
        return *this;
    }

private:
    byte& m_byte;
    const byte m_mask;
};

Generally I would recommend avoiding things like this that rely on sneaky implicit conversions in C++ because it really messes with your intuition, and it doesn't play nicely with things like auto and decltype in C++11.

Upvotes: 7

Pubby
Pubby

Reputation: 53037

You can't.

You're best bet would be to return a proxy object.

Starting point:

struct bit {
  bit(Vector<bool>* vec, size_t pos);
  bit& operator=(const bool& b);
  operator bool();
  Vector<bool>* vec;
  size_t pos;
};

bit Vector<bool>::operator[](size_t pos) {
 return bit(this, pos);
};

Upvotes: 3

Cat Plus Plus
Cat Plus Plus

Reputation: 129764

You cannot do that by returning a reference to bool. You need to create and return a proxy object instead, and overload its assignment operator, something like

struct bit_access_proxy {
    bit_access_proxy(int& carrier, int bit) { ... }
    operator bool() const {
        // return the value of the bit
    }
    bit_access_proxy& operator=(bool new_bit) {
        // set the value of the bit
    }
};

bit_access_proxy Vector<bool>::operator[](int i) { ... }

Upvotes: 4

Kerrek SB
Kerrek SB

Reputation: 476980

You cannot have references to individual bits. You can only have references to variables.

The closes thing you could do is make a proxy class which exposes a reference to a bool and which maintains an internal reference to the base integer as well as the necessary bitfiddling mechanics; then make your []-operator return such a proxy object.

Upvotes: 2

Related Questions