AvinashK
AvinashK

Reputation: 3423

const overloaded operator[] function and its invocation

I define two versions of overloaded operator[] function in a class array. ptr is a pointer to first element of the array object.

int& array::operator[] (int sub) {  
   return ptr[sub];
} 

and

int array::operator[] (int sub) const { 
  return ptr[sub];
}

Now, if I define a const object integer1 the second function can only be called..... but if I make a non-const object and then invoke as below:

cout << "3rd value is" << integer1[2];

which function is called here?

Upvotes: 4

Views: 2308

Answers (2)

Jerry Coffin
Jerry Coffin

Reputation: 490178

In your second example, the non-const version will be called, because no conversion is required, and a call that requires no conversion is a better match than one that requires a conversion.

Ultimately, however, you have a basic problem here: what you really want is behavior that changes depending on whether you're using your object as an rvalue or an lvalue, and const doesn't really do that. To make it work correctly, you normally want to return a proxy object, and overload operator= and operator T for the proxy object:

template <class T>
class myarray { 
    T *ptr;

    class proxy { 
        T &val;
        proxy &operator=(proxy const &p); // assignment not allowed.
    public:
        proxy(T &t) : val(t) {}
        operator T() const { return val; }
        proxy &operator=(T const&t) { val = t; return *this; }
    };

    proxy const operator[](int sub) const { return proxy(ptr[sub]); }
    proxy operator[](int sub) { return proxy(ptr[sub]); }
    // obviously other stuff like ctors needed.
};

Now we get sane behavior -- when/if our array<int> (or whatever type) is const, our operator[] const will be used, and it'll give a const proxy. Since its assignment operators are not const, attempting to use them will fail (won't compile).

OTOH, if the original array<int> was not const, we'll get a non-const proxy, in which case we can use both operator T and operator=, and be able to both read and write the value in the array<int>.

Upvotes: 2

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385194

Your const version should return const int& not int, so that the semantics are just the same between the two functions.

Once you've done that, it doesn't matter which one is used. If the const version has to be used because your object has a const context, then it will be... and it won't matter as you're not trying to modify anything. Otherwise, it'll use the non-const version... but with just the same effect.

Upvotes: 2

Related Questions