Reputation: 31
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
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
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
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