2

I am learning C++ and studying Chapter 18 of Vandevoorde and Josuttis's C++ Templates. I retyped their code for Expression Templates, but the following is producing the error

sarray1.cpp:36:6: error: ‘T& SArray<T>::operator[](size_t) const’ cannot be overloaded
   T& operator[] (size_t idx) const {
      ^
sarray1.cpp:32:5: error: with ‘T SArray<T>::operator[](size_t) const’
   T operator[] (size_t idx) const {

Here's the code:

template <typename T>
class SArray {

public:

...

  T operator[] (size_t idx) const {
    return storage[idx];
  }

  T& operator[] (size_t idx) const {
    return storage[idx];
  }
...
};

I am just learning C++ so I hadn't seen an instance of an overloaded function that differed only be return type, but I see that this is indeed done: Overload a C++ function according to the return value. I also see that [] is not on the list of operators that cannot be overloaded in C++. I can't think of what else could be going wrong. What is the reason for the above error?

Community
  • 1
  • 1
sunny
  • 3,853
  • 5
  • 32
  • 62
  • Not sure, but seems to be related: [Const and Non-Const Operator Overloading](http://stackoverflow.com/questions/19237411/const-and-non-const-operator-overloading) if the `const` on the `T&` version is a mistake? – crashmstr Jul 27 '15 at 16:07
  • Yes, the const on the second line is a mistake, as was shown in one of the answers below. However, I'll leave the question un edited so the reply makes sense. Sorry about this type, all. – sunny Jul 27 '15 at 16:07

3 Answers3

4

You made a mistake when re-typing the code from page 323. Only the first overload should be const, while the second one should be non-const:

T operator[] (size_t idx) const {
    return storage[idx];
}

T& operator[] (size_t idx) { // <<== No const here
    return storage[idx];
}

The point this code is trying to illustrate is that you can overload an operator on const-ness of this object. C++ will figure out from the context which of the two operators it should call, and then either return a reference when SArray is non-const, or return a copy when the array is const.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    Ugh, you're right. What a terrible question. My apologies. – sunny Jul 27 '15 at 16:07
  • 1
    @sunny No worries here: overloading on `const` is a particularly tough thing to spot if you have never seen this trick before. Good news is that it makes you watch out for `const`-ness of operators in the future, helping you avoid potential confusion. – Sergey Kalinichenko Jul 27 '15 at 16:12
1

Strictly speaking, you can't overload on the return type. If you read the question and answer that you linked (Overload a C++ function according to the return value), you would see that a workaround is required.

However, you really have to ask what you are doing this? Is there a simpler solution?

You probably should have one const method, and one non-const method:

const T& operator[] (size_t idx) const {
  return storage[idx];
}

T& operator[] (size_t idx)  {
  return storage[idx];
}
Community
  • 1
  • 1
Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
1

You cannot overload by return type in C++. What's considered are the arguments and, for member functions, the qualification. In this case, I'm guessing what you meant to do was:

// a non-const member function to return a non-const reference
T& operator[] (size_t idx) {
    return storage[idx];
}

// a const member function to return a const reference
const T& operator[] (size_t idx) const {
    return storage[idx];
}

This way, the const member function will be called if this is a pointer to const (because the non-const function is not viable) and the non-const function will be called otherwise (because it will be a better match).

Barry
  • 286,269
  • 29
  • 621
  • 977