Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With C++, how do I wrap a vector and overload [] for all types?

Long story short, I have

#include <vector>

template <class T>
class wrapped_vector {
private:
        std::vector<T> elements;
public:
        wrapped_vector() {
                elements.resize(20);
        }

        T& operator[](int i) {
                return elements[i];
        }

        const T& operator[](int i) const {
                return elements[i];
        }
};

int main(void) {
        wrapped_vector<int> test_int;
        test_int[0] = 1;

        wrapped_vector<bool> test_bool;
        test_bool[0] = true; // remove this line and it all compiles
}

and it gives me the compile error

test.cpp: In instantiation of ‘T& wrapped_vector<T>::operator[](int) [with T = bool]’:
test.cpp:28:13:   required from here
test.cpp:15:34: error: invalid initialization of non-const reference of type ‘bool&’ from an rvalue of type ‘std::vector<bool, std::allocator<bool> >::reference {aka std::_Bit_reference}’
like image 493
Christian Neverdal Avatar asked Jan 29 '13 22:01

Christian Neverdal


1 Answers

You got bitten by yet another side-effect of the "magic" std::vector<bool>.

Since std::vector<bool> doesn't actually store a contiguous array of bools, but packs them as a bitset, it cannot return a "real" reference to a bit in the middle of the bitset (since bits aren't directly addressable); for this reason, its operator[] returns a proxy object that, overloading its operator=, "fakes" a reference semantic.

The problem lies here: this proxy object is not a bool &, so you cannot return it as such in your method.

The simplest way to solve would be something like this:

    typename std::vector<T>::reference operator[](int i) {
            return elements[i];
    }

    typename std::vector<T>::const_reference operator[](int i) const {
            return elements[i];
    }

that guarantees that you actually return whatever type std::vector uses as "reference to T" in its methods.

Also, you may want to use std::vector<T>::size_type for indexes (mostly for coherency of your forwarder functions than anything else).

like image 147
Matteo Italia Avatar answered Oct 17 '22 19:10

Matteo Italia