I'm working on a bit vector class that I'm using in a current project.
Basicly BitVector is a container class for storing and manipulating data a bit level.
I have two member fuctions for "setting" and "getting" bits at a given index.

// Returns the bit at the specified index.
unsigned char BitVector::at(int index) 
{
    if (index < 0 || index >= size)
        throw; // ("Index outside the range of vector: " + index);

    int byteValue = vector[index >> 3] & 0xff;
    return (unsigned char)((byteValue >> (7 - (index & 0x7))) & 1);
}

// Replaces the bit at index with that specified by value.
void BitVector::replace(int index, unsigned char value)
{
    if (index < 0 || index >= size)
        throw ;// ("Index outside the range of vector: " + index);

    if (!(value == 0 || value == 1))
        throw; // ("Invalid value for bit vector: " + value);

    int byteValue = vector[index >> 3] & 0xff;
    if (value == 1)
        byteValue = (unsigned char)(byteValue | (1 << (7 - (index & 0x7))));     // Left shift 1, then bitwise OR.

    else
        byteValue = (unsigned char)(byteValue & ~(1 << (7 - (index & 0x7))));    // Left shift 1, take complement, then bitwise AND.

    vector[index >> 3] = (unsigned char)(byteValue & 0xff);
}

I would like to implement the subscript operater "[]" as a simpler/clearer way of accessing the bit data rather than using the above functions.

So far I have this:

unsigned char& BitVector::operator[](int index) const
{
    assert(index >= 0 || index < size);

    int byteValue = vector[index >> 3] & 0xff;
    unsigned char rtn_value = (unsigned char)((byteValue >> (7 - (index & 0x7))) & 1);
    //unsigned char rtn_value = at(index);
    return (unsigned char&)rtn_value;
}

As this member function requires code to extract the required bit from the byte, it can not be used to both 'get' and 'set'.
Is there any way can achieve this with the subscript operator?
Thanks in advance...
Milton

Recommended Answers

All 4 Replies

iamthwee
I have read this article and this is fine if you are 'setting' or 'getting' an element with the array. In my case I need to get or set a bit within the element, not the element itself.
Cheers Milton

You should be able to overload the function such that it will use one with a constant function and another with a non-const function. First, let's simplify the existing functions a bit and make them more modern:

// these two utility functions should be private and inline, 
// but I'll write them like this for now.

int BitVector::byte_index(int index)
{
    return index >> 3;
}

uint8_t BitVector::isolate(int index)
{
    assert(index >= 0 || index < size);
    return vector[byte_index(index)];
}

// Returns the bit at the specified index.
uint8_t BitVector::at(int index) 
{
    return static_cast<uint8_t>((isolate(index) >> (7 - (index & 0x7))) & 1);
}

// Replaces the bit at index with that specified by value.
void BitVector::set(int index, uint8_t value)
{
    assert(value == 0 || value == 1);
    uint8_t byteValue = static_cast<uint8_t>(isolate(index) | (1 << (7 - (index & 0x7))));

    vector[byte_index(index)] = byteValue & 0xff;
}

uint8_t& BitVector::operator[](int index) const
{
    uint8_t rtn_value = at(index);
    return static_cast<uint8_t&>(rtn_value);
}

BvHelper BitVector::operator[](int index)
{
    return BvHelper(this, index);
}

Now add a class BvHelper that handles the getter and setter cases, as described here:

class BvHelper 
{
private:
    BitVector& vec;
    int index;

public:
    BvHelper(BitVector& bv, int idx): vec(bv), index(idx)
    {}

    uint8_t& operator int () const
    {
        return vec.at(index);
    }

    uint8_t& operator = (int value)
    {
        return vec.set(index, value);
    }
}

You may need to tinker with this a bit.

commented: deep knowledge +15

Schol-R-LEA
Thanks for the reply, the helper method works fine, with a bit of tinkering.
This is what I ended up with:
Header File

#pragma once

#include <string>
#include <stdint.h>

using namespace std;

class BitVectorHelper;  // Forward reference.

class BitVector
{

private:
    static const int DefaultSize = 32;
    uint8_t* vector;
    int size;
    int length;

public:
    BitVector(void);
    ~BitVector(void);

    uint8_t* byte_array(void);
    int size_in_bits(void);
    int size_in_bytes(void);
    int capacity(void);
    void append_bits(int value, int number_of_bits);
    void append_bit(uint8_t value);
    uint8_t at(int index);
    void set(int index, uint8_t value);
    void insert(int index, uint8_t value);
    void remove(int index, int count);
    void clear(void);
    string to_string(void);

    //uint8_t& operator[](int index) const;     // don't need this!!!
    BitVectorHelper operator[](int index);

private:
    void append_byte(uint8_t value);
    inline int byte_index(int index);
    inline uint8_t get_byte(int index);
};

class BitVectorHelper       // Maybe nest this class in the BitVector class????? 
{
private:
    BitVector* bit_vector;
    int index;

public:
    BitVectorHelper(BitVector* bv, int idx): bit_vector(bv), index(idx)
    {}

    operator int () const
    {
        return bit_vector->at(index);
    }

    void operator = (int value)
    {
        bit_vector->set(index, value);
    }
};

Member Function

// Overload the subscript operator.
BitVectorHelper BitVector::operator[](int index)
{
    return BitVectorHelper(this, index);
}

Thanks again for you help
Milton

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.