-2

Can anybody explain the difference (if there is any) between the 2 versions of this [] operator? Both version are working fine ...

class Test {

    int arr[100];

    int operator[](int i) {
        return arr[i];
    }

    int & operator[](int i) {
        return arr[i];
    }
};


Test a;
a.arr[5] = 10;

// works for both versions:
int n = a[5];
nil_dib
  • 51
  • 1
  • Why didn't you use the same operator for the assignment of `10`? `Test::arr` is private, after all... – LogicStuff Aug 26 '19 at 11:00
  • 5
    I don't see how this could work in any version. _Everything_ in the class is private. – Ted Lyngmo Aug 26 '19 at 11:07
  • 1
    Considering that the code needed for either variant is *very* small, you could easily create two separate [mcve] to showcase each variant. It might have been better. – Some programmer dude Aug 26 '19 at 11:08
  • 2
    ^^, in addition to @Ted 's comment, you can not overload a function for the return type. – JeJo Aug 26 '19 at 11:09
  • And you should *really* invest in [a couple of good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) to read. Especially the chapters or sections on *references*. – Some programmer dude Aug 26 '19 at 11:09
  • One returns by value, so `a[5] = n` is not possible, and the other returns by reference, so `a[5] = n` is possible. However, a class cannot have both versions simultaneously. – Peter Aug 26 '19 at 11:25
  • 1
    @Peter Not quite true, a class *can* have both variants, if the first one is marked a `const`. As in `int operator[](int i) const;`. The `const`-ness of a member function is part of overload resolution. – Some programmer dude Aug 26 '19 at 11:34
  • @Someprogrammerdude - Yes, I know that, but the example given marked neither version with `const` qualifiers, so my comment was directed accordingly. – Peter Aug 26 '19 at 12:15

2 Answers2

2

First, you must make your operators accessible:

class Test {
private: 
    int arr[100];

public:
    int operator[](int i) {
        return arr[i];
    }    
    int& operator[](int i) {
        return arr[i];
    }
};

Now, this won't compile (since arr is private):

Test a;
a.arr[5] = 10;

int operator[](int i) returns by value (an rvalue), making a[5] = 10; impossible.

int& operator[](int i) returns a reference to the int stored in arr (an lvalue) which makes a[5] = 10; possible.

But it won't compile since your operators only differ on the return types (int vs. int&). Making the one returning by value const solves that issue:

#include <iostream>

class Test {
private:
    int arr[100];

public:
    int operator[](size_t i) const { // note the const
        std::cout << "using operator[]() const\n";
        return arr[i];
    }
    int& operator[](size_t i) {
        std::cout << "using operator[]() mutable\n";
        return arr[i];
    }
};

void test_const(const Test& t) {
    std::cout << t[5] << "\n";
}

int main() {
    Test a;
    a[5] = 10;
    std::cout << a[5] << "\n";
    test_const(a);
}

Output:

using operator[]() mutable
using operator[]() mutable
10
using operator[]() const
10
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • sorry missleading... the code was meant to be pseudo ... maybe this is more clear – nil_dib Aug 26 '19 at 11:59
  • `class TestA { public: int arr[100]; int operator[](int i) { return arr[i]; } }; class TestB { public: int arr[100]; int & operator[](int i) { return arr[i]; } }; TestA a; a.arr[5] = 10; int n = a[5]; // n is 10 TestB b; b.arr[5] = 10; int k = b[5]; // k is 10` – nil_dib Aug 26 '19 at 12:09
  • @nil_dib In the above you don't have a conflict between the operators since they are in different classes. You've made `arr` public though which bypasses the operators completely so why even add operators? If your operator returns a reference to a mutable value, you can do `a[5] = 10` but if it returns by value, you can't change the value stored in `arr` via the operator. See the `const`/`mutable` comments in my code. – Ted Lyngmo Aug 26 '19 at 12:15
  • basically my question is: what is the difference between these 2 operator implementations 1. int operator[](int i) 2. int & operator[](int i) – nil_dib Aug 26 '19 at 12:19
  • @nil_dib Added explanation for that in the answer. Make `arr` private and it'll be easier to understand too. – Ted Lyngmo Aug 26 '19 at 12:37
0

First, you must make your operators accessible:

class Test {
private: 
    int arr[100];

public:
    int operator[](int i) {
        return arr[i];
    }  // -> Case 1  
    int& operator[](int i) {
        return arr[i];
    } // ->Case 2
};

The difference between above two operators is -

Case 1 -> you can use it only as R value.

Case 2 -> you can use it as "R value" as well as "L value".