From: rmartin@willing.Rational.COM (Bob Martin)
Newsgroups: comp.lang.c++
Subject: Re: overloading [] for bitvectors?
Date: 14 Apr 92 23:19:41 GMT

Garym@qube.OCUnix.On.Ca (Garym) writes:

>A few days ago, I passed by a posting here dealing with overloading
>the [] and = operators; at the time it didn't seem that important, but
>now I wonder.

>What I want to do is pure syntactic sugar, but it would be very nice
>and a noble gesture of implementation hiding.  I have a bit-array class
>to store large lists of bit values in a compact form, and in a nutshell
>what I would like are statements like the following:

>     bitvector[17] = TRUE;
>     if (bitvector[3]) do_something();


Below is the code for the class BitVector, which behaves as you
describe above.  The trick is to make operator[] return a "helper
object" which is a friend of the BitVector.  This helper has an
operator int() method for when it is used as an rvalue, and an
operator= method for when it is used as an lvalue.

---------- bit.hh ---------------
//
//  BitVector
//
//  This class acts just like an array of bits.  You can
//  use the [] operator to address the bits in the array.
//
//  A BitVector is constructed as follows:
//
//    BitVector v(1000); // defines a vector of 1000 bits.
//
//  The bits can be accesses as follows:
//
//    for (int i=0; i<1000; i++)
//    {
//        v[i] = 0;
//    }
//
//  You can also assign values to bits as follows:
//
//    v[7] = 0;
//    v[84] = 1;
//
//  When assigning bit values, the rvalue is converted to a bit
//  using the following expression:   (rvalue != 0).  Thus, any
//  nonzero value yeilds a bit of '1'.
//

class BitVector
{
  public:
    BitVector(int=32);
    BitVector(const BitVector&);
    virtual ~BitVector();

    class BitRef operator[] (int);
    BitVector& operator= (const BitVector&);

  protected:

  private:
    int itsDimension;
    char* itsBits;

  friend class BitRef;
};

class BitRef
{
  public:
    operator int();
    BitRef& operator=(const int);

  protected:

  private:
    BitRef(BitVector&, int theIndex);
    BitRef(const BitRef&);

    int itsIndex;
    BitVector& itsVector;

  friend BitVector;
};

---------- bit.cc ----------------------
//
//  bit.cc -- Implementation module for BitVector
//

#include "bit.hh"
#include <memory.h>
#include <assert.h>


const static int bitsPerChar = 8;

inline static int CharSize(int theSize)
{
    int charSize = theSize/bitsPerChar;
    int remainder = theSize%bitsPerChar;
    charSize += (remainder == 0 ? 0 : 1);
    return charSize;
}

BitVector::BitVector(int theSize)
{
    itsBits = new char[CharSize(theSize)];
    itsDimension = theSize;
    for (int i=0; i<CharSize(theSize); i++)
        itsBits[i] = 0;
}

BitVector::BitVector(const BitVector& theVector)
{
    itsBits = 0;
    *this = theVector;
}

BitVector::~BitVector()
{
    delete itsBits;
}

BitRef BitVector::operator[] (int theIndex)
{
    assert(theIndex <= itsDimension);
    return (BitRef(*this, theIndex));
}

BitVector& BitVector::operator= (const BitVector& theVector)
{
    itsDimension = theVector.itsDimension;
    delete itsBits;
    itsBits = new char[CharSize(itsDimension)];
    memcpy(itsBits, theVector.itsBits, CharSize(itsDimension));
    return *this;
}

BitRef::BitRef(BitVector& theVector, int theIndex)
: itsIndex(theIndex)
, itsVector(theVector)
{
}

BitRef::BitRef(const BitRef& theRef)
: itsIndex(theRef.itsIndex)
, itsVector(theRef.itsVector)
{
}

BitRef::operator int()
{
    int charIndex = itsIndex/bitsPerChar;
    int bitIndex = itsIndex%bitsPerChar;
    char bitChar = itsVector.itsBits[charIndex];
    int bit = (bitChar >> bitIndex) & 1;
    return bit;
}

BitRef& BitRef::operator=(const int theBit)
{
    int charIndex = itsIndex/bitsPerChar;
    int bitIndex = itsIndex%bitsPerChar;
    char bitChar = (theBit != 0);
    bitChar <<= bitIndex;
    char bitPos = 1;
    bitPos <<= bitIndex;
    itsVector.itsBits[charIndex] &= ~bitPos;
    itsVector.itsBits[charIndex] |= bitChar;
    return *this;
}
----------------------------------------

Share and enjoy.



--
+---Robert C. Martin---+-RRR---CCC-M-----M-| R.C.M. Consulting         |
| rmartin@rational.com |-R--R-C----M-M-M-M-| C++/C/Unix Engineering    |
|     (Uncle Bob.)     |-RRR--C----M--M--M-| OOA/OOD/OOP Training      |
+----------------------+-R--R--CCC-M-----M-| Product Design & Devel.   |