Thex
Thex

Reputation: 31

Square brackets overloading => no operator matches operands

I'm currently having a bit of trouble overloading the square brackets in a custom vector class.

My class basically looks like this:

typedef uint32_t u32; // This is not actually here, but so you get the idea. Also, it is included in the problematic call's file

template<class T>
class JFFVector
{
public:
    //Init and stuff
    T& operator[](u32 iIndex)
    {
        return m_pData[iIndex + miDataOffset];
    }

private:
    T* m_pData;
    u32 m_iDataOffset;
}

And within this classes functions, I can call (*this)[0] and everything works. Now the issue I'm having is with a class that has a member as follows:

class TOtherClass
{
public:
    // Stuff
    void DoSomething() const
    {
        for (u32 i; i < m_tItems.size(); ++i)
            m_tItems[i]->DoStuff(); // Which is a const function
    }

private:
    JFFVector<const JFFItem*> m_tItems;
}

The issue being that my compiler throws an error at my face saying

no operator "[]" matches these operands

operand types are: const JFFVector[u32]

typedef uint32_t u32.

So one thing I noticed is that if I make m_tItems a pointer, then I can do "(*m_tItems)[i]->DoStuff()" and it works fine. But I do not understand why this works while it doesn't with a non-pointer version. (Also, I tried with a simple int instead of u32, and, with no surprise, it didn't work)

Does anyone have any idea what I did wrong please? And, if not trivial, why is it wrong?

(Sorry if this has been answered already, I tried searching for a similar issue but found nothing that looks like this issue)

Upvotes: 0

Views: 498

Answers (3)

user4581301
user4581301

Reputation: 33931

When in const, one must stay const. The compiler has no easy way to know that what happens in m_tItems[i] does not change m_tItems and thus violate the promise that void DoSomething() const would not change the state of TOtherClass.

Solution: Implement a const operator[]

const T& operator[](u32 iIndex) const 
{
    return m_pData[iIndex + miDataOffset];
}

Upvotes: 1

Cameron
Cameron

Reputation: 98746

There's two indexing operators you can overload -- one which works on a const JFFVector and returns a T const&, and one which works on a JFFVector and returns a T&. You've only implemented the second.

You can implement it similarly to the non-const version like so:

T const& operator[](u32 iIndex) const   // <-- note the two `const`s
{
    return m_pData[iIndex + miDataOffset];
}

Note that this overloading is not specific to operator[], but rather all methods (which can be overloaded by const or non-const).

The reason you need the const version in your code is that DoSomething() is declared const, thus this is const TOtherClass* within that method, and by extension all its members, notably m_tItems here, are const within the method, and so only const methods can be called on them. Since there is no const version of operator[] defined for m_tItems, the compiler gives you that error.

Upvotes: 2

Danh
Danh

Reputation: 6016

You need 2 version, one for const and one without const. One for the immutable const JFFVector and one for mutable JFFVector.

In this case, DoSomething is a const function, it want to call a const function.

template<class T>
class JFFVector
{
public:
    //Init and stuff
    T& operator[](u32 iIndex)
    {
        return m_pData[iIndex + miDataOffset];
    }
    const T& operator[](u32 iIndex) const
    {
        return m_pData[iIndex + miDataOffset];
    }

private:
    T* m_pData;
    u32 m_iDataOffset;
}

Upvotes: 0

Related Questions