Alon Shmiel
Alon Shmiel

Reputation: 7121

Definition of operators

I am trying to define some operators.

I do it according to this documentation:

http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html

Is there an operator that should be defined twice?

I think that it's the index operator. am I right? I defined it such as:

int operator [] (const int power) const{
    // here there is some code
}

Assuming I implement it correctly, what's about the operator that should have be defined twice?

Does it support the next things?

a[1] = 3;
cout << a[1]; // I defined the << operator

any help appreciated!

Upvotes: 1

Views: 102

Answers (3)

6502
6502

Reputation: 114461

To support assignment there are two options

  1. The indexing operator [] returns a reference
  2. The indexing operator [] returns a proxy object that implements assignment

The first case is the simplest, but doesn't allow you to distinguish between read and write operations. The second method is a bit more complex but allows more control:

An example of approach (2) is the following

struct MyArray {
    std::vector<int> v;

    MyArray(int n) : v(n) {}

    struct ItemRef {
        MyArray& a;
        int index;

        ItemRef(MyArray& a, int index)
          : a(a), index(index)
        {}

        int operator=(int x) {
            printf("Writing to element %i\n", index);
            a.v[index] = x;
            return x;
        }

        operator int() {
            printf("Reading element %i\n", index);
            return a.v[index];
        }
    };

    ItemRef operator[](int index) {
        if (index < 0 || index >= int(v.size()))
            throw std::runtime_error("Invalid index");
        return ItemRef(*this, index);
    };
};

Upvotes: 1

Andy Prowl
Andy Prowl

Reputation: 126412

I think that it's the index operator. am I right?

Almost. It is called the subscript operator, and it must accept one single argument. Your operator accepts two, and that makes your code illegal.

Does it support the next things?

Supposing you have a properly written operator [] (without knowing some context from the logic of your application I cannot tell how to write one), then both the instructions you mention should be supported.

However, in order for this:

a[1] = 3;

To be legal (if a fundamental type is returned), operator [] should return an lvalue reference - therefore, int& and not int. Of course, this means the object to which the lvalue reference is bound cannot be a local object or a temporary, because that would mean returning a dangling reference.

int& operator [] (const int power) { // <== The function cannot be "const" if you
// ^                                 //     are returning a non-const lvalue ref
                                     //     to a data member or element of a data
                                     //     member array
    // here there is some code
}

You may also want a const version of the subscript operator:

int operator [] (const int power) const {
// No need to use a int const&    ^^^^^
// here, that is basically the    This member function can be const, since it is
// same as returning an int by    neither modifying the object on which it is
// value                          invoked, nor returns any non-const lvalue ref
                                  to a data member or an element of data member
    // here there is some code
}

Upvotes: 2

NPE
NPE

Reputation: 500167

You may want to have both a const and a non-const versions of the operator:

int operator[](int index) const { ... }
int& operator[](int index) { ... }

This will permit both usages given in your example. It will also permit the second usage even if a is const.

Upvotes: 2

Related Questions