-1

I am trying to write a C++ template class which contains an array of bits (as a member variable). The size of the bit-array is known at compile time, so I'd really like it to be a std::bitset, but I'm having difficulty writing an operator[] function to set the bits.

For example, I'd like my class to start out something like this:

template<size_t N>
class bitvector
{
public:
    bool operator[](size_t i) const { return bits[i]; }
    bool& operator[](size_t i) { return bits[i]; }
private:
    std::bitset<N> bits;
};

The getter works okay. The problem is that the std::bitset::operator[] setter function returns a std::bitset::reference (not a bool&) which is itself templated. I'm not too experienced with templates, but the following attempt failed:

template<size_t K>
std::bitset<K>::reference operator[](size_t i) { return bits[i]; }

with the following error need 'typename' before 'std::bitset<K>::reference' because 'std::bitset<K>' is a dependent scope. I tried some googling, but to no avail.

Is std::bitset a suitable tool for this task? If so, how can I write the setter function? If not, what can I use instead? (I would still like it to be actually stored as bits, and std::vector<bool> doesn't seem quite right, as I want the array size to be strictly fixed at compile time).

Harry
  • 884
  • 1
  • 8
  • 19
  • 2
    I don't understand. The `std::bitset` [has an `operator[]`](http://en.cppreference.com/w/cpp/utility/bitset/operator_at), so why are you reinventing the wheel? – Thomas Matthews Apr 12 '16 at 19:00
  • 3
    it seems the error is self explanatory. add `typename before...`. So why don't you try doing that? – Nowhere Man Apr 12 '16 at 19:00
  • 1
    @ThomasMatthews: Probably a minimal version of a larger class to demonstrate the problem. – Unimportant Apr 12 '16 at 19:00
  • @ThomasMatthews As pointed out in another comment, I was trying to give a minimal example from what will be a much larger class. – Harry Apr 12 '16 at 19:17
  • @NowhereMan Of course, I did try doing that, but it produced a host of new errors that seemed to be leading me off in the wrong direction. – Harry Apr 12 '16 at 19:21

1 Answers1

3

You can just return a std::bitset<N>::reference as follows:

template<size_t N>
class bitvector
{
public:
    bool operator[](size_t i) const { return bits[i]; }
    typename std::bitset<N>::reference operator[](size_t i) { return bits[i]; }
private:
    std::bitset<N> bits;
};

There's no need to have the additional template<size_t K> since you can still access the original template parameter N, and under no circumstances would you want the N and your K to be different.

You need the typename before the function's return type to tell the compiler the ::reference is a type rather than a value.

For example:

struct Foo{
   typedef int reference;
};

struct Bar{
    static int reference;
};

Here Foo::reference is a type, but Bar::reference is a variable, without the typename before the return type the compiler will complain as it could be that std::bitset<N>::reference is a variable. (The compiler should have all the information it needs to work out that it isn't a value, but for some reason it is required anyway).

jtedit
  • 1,450
  • 2
  • 13
  • 27