views:

496

answers:

6

I have a C++ class that overloads operator[], the array subscript/brackets operator. This is awfully convenient outside of my class, where I can write foo[bar]. However, I can't figure out how to use this notation when I'm implementing methods inside my class.

I know I can write operator[](bar) or this->operator[](bar) but those are fairly unwieldy and take away a lot of the convenience of the operator in the first place. (I also know I can just add a new method that calls the operator.) Is there a way I can write this[bar] or this->[bar] or something similarly nice?

Note: This question may also apply to the many unary operators (e.g., how can I call foo++ from within the class?), but I personally only care about operator[].

Edit: I realized soon after posting that I can use (*this)[bar]. All of the answers so far have suggested this as well. Are there any other alternatives?

+8  A: 
(*this)[bar];

works fine for me.

Evan Teran
If anyone has other alternatives, please let me know. Until then (if ever), I'm accepting this answer. Thanks.
A. Rex
+2  A: 

Use

(*this)[bar]

because you want to call the operator[] on an instance, not a pointer to an instance (which is what this[bar] signifies).

Mr Fooz
+1  A: 

You could use (*this)[bar], but that might not be much of an improvement...

Drew Hall
+2  A: 

An alternative to (*this)[bar] is to use a named member function that does the work of operator[]. Overloaded operators make things easier on your users. More importantly, they are part of your class' interface. Ask yourself if it really makes sense to implement your class in terms of its own public interface. If not, I suggest writing a separate (protected or private) member function to do the work, and then have operator[] and any other function call it.

Kristo
+3  A: 

I use a at() function, and have the operator[] call the at() function behind the scenes, so operator[] is just syntactic sugar. That's how std::vector does it, so it seems like a reasonable (with precedence) way to do it.

Now for a complete syntactic sugar hack (can't say I fully recommend it but might strike your fancy):

class Widget
{
    Widget&  self;
public:
    Widget() :self(*this)
    {}

    void operator[](int)
    {
     printf("hello");
    }

    void test()
    {
        //scripting like sugar
        //you pay the price of an extra reference per class though
     self[1]; 
    }
};


int main(int argc, char* argv[])
{
    Widget w;
    w[1];
    w.test();
    return 0;
}

Also if you want to do this for free, without paying the cost of the reference, AND are a follower of some evil sect dedicated to making programmers suffer you could do:

#define self (*this)

Actually I think that's how most handles are implemented in Apple's NS API...

Robert Gould
I do like this, in a sense, because the way I've been doing it for the past few minutes has been setting self = *this and then using self. Thanks.
A. Rex
Vector is the other way around, because vector::at() has to do range checking before calling operator[]()
MSalters
+1  A: 

That's how std::vector does it...

vector::at() function checks boundary and returns out_of_range exception when appropriate: source.

Donotalo