Xavier
Xavier

Reputation: 9049

How do I fix a bracket/index operator overload when the variable being operated on is const?

I have a template for a 3D array however I'm having problems compiling when a variable of type Chunk (see typedef below) tries to do an index access.

template <typename T, int xMax, int yMax, int zMax>
class Volume {
public:
    class HelperIndex3 {
    public:
        HelperIndex3(Volume& p, int xx, int yy) : parent(p), x(xx), y(yy) {}
        T operator[] (int z) const {return parent.data[x][y][z];}
        T& operator[] (int z) {return parent.data[x][y][z];}
    private:
        Volume& parent;
        int x;
        int y;
    };
    class HelperIndex2 {
    public:
        HelperIndex2(Volume& p, int xx) : parent(p), x(xx) {}
        HelperIndex3 operator[] (int y) const {return HelperIndex3(parent, x, y);}
        HelperIndex3 operator[] (int y) {return HelperIndex3(parent, x, y);}
    private:
        Volume& parent;
        int x;
    };
    HelperIndex2 operator[] (int x) const {return HelperIndex2(*this, x);} //problem at this line
    HelperIndex2 operator[] (int x) {return HelperIndex2(*this, x);}

private:
    T data[xMax][yMax][zMax];
};

typedef Volume<unsigned char, 64, 64, 64> Chunk;

The problem line appears to want a const Volume& p in the HelperIndex2 constructor which I guess makes sense since I'm trying to use a const Chunk elsewhere - but I don't know how to fix this. If I add a second constructor am I supposed to maintain two parent references one that is constant and another that is not? I fear this is going to balloon into a mess. If someone could explain the right way of handling this situation I would greatly appreciate it.

Upvotes: 0

Views: 103

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 476990

You won't get around maintaining two sets of proxy classes. This is completely analogous to the iterator and const_iterator nested classes of standard library containers.

Since you are returning a copy of the proxy class, the proxy class that contains a mutable reference to the original object cannot possibly also be used for constant-only access to the original object, so you cannot get around some sort of two-fold approach. The semantics of the two are different: If all you have is an instance of the proxy class, you have to be able to know whether it allows mutating or only read-only access.

Upvotes: 1

Related Questions