3

Why does it require to be a member function of a class for its operation and is good to return a reference to private member?

class X
{
public:

    int& operator[] (const size_t);
    const int &operator[] (const size_t) const;

private:
    static std::vector<int> data;
};

int v[] = {0, 1, 2, 3, 4, 5};
std::vector<int> X::data(v, v+6);

int& X::operator[] (const size_t index)
{
    return data[index];
}

const int& X::operator[] (const size_t index) const
{
    return data[index];
}
user963241
  • 6,758
  • 19
  • 65
  • 93
  • What is your question, exactly? – erikkallen Mar 04 '11 at 13:19
  • possible duplicate of [Should accessors return values or constant references?](http://stackoverflow.com/questions/4613823/should-accessors-return-values-or-constant-references) – fredoverflow Mar 04 '11 at 13:24
  • @FredOverflow: I think this question has two parts to it, only one of which is the return reference or value part of it. The other part would be: why does `operator[]` need to be a member function? – David Rodríguez - dribeas Mar 04 '11 at 13:31

4 Answers4

3
  • As to why is it required to have [] as a member, you can read this question (by yours sincerely). Seems it's just the way it is with no really really convincing explanation.

  • As to why return reference? Because you want to provide a way not only to read, but also (for non-const objects) to modify the data. If the return weren't a reference (or some proxyr)

    v[i] = 4;

    wouldn't work.

HTH

Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
2

It needs to be a member function according to 13.5.5:

operator[] shall be a non-static member function with exactly one parameter. It implements the subscripting syntax

A reference to a private member is completely OK and pretty common. You hide the details from the user of your class, but still provide the functionality you need (ability to modify individual elements)

Your data variable likely shoudn't be static though, unless you really want to share it among all instances of your class

Erik
  • 88,732
  • 13
  • 198
  • 189
2

For the first question, it is just the way they decided it had to be, i.e. you can't do:

T operator[]( const X &, size_t );

as an external function.

And yes, you are fine returning a reference to a private member, non-const if you allow your users to write there, non-const otherwise.

In your example though data is static, which does not make sense if that is the source for what it returns.

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • More importantly, a reference returned by `X::operator[]` can become invalid when the underlying vector is reallocated. – suszterpatt Mar 04 '11 at 13:23
  • 1
    You wrote `non-const if you allow your users to write there, non-const otherwise`. Assuming you meant `const otherwise` at the end there. – Sion Sheevok Mar 04 '11 at 13:33
-1

What would the syntax be for calling a non-member operator[]? Any syntax for that would be awkward. operator[] takes ones parameter within the [ and ] and that is usually an index or some kind of data necessary to find an object.

Also, yes, it is a good idea to return a reference, even if it's a private member. That is exactly what STL vectors do and just about any other class I can think of that I've ever used that provides operator[]. It would be advised that it the usage is maintained.

Sion Sheevok
  • 4,057
  • 2
  • 21
  • 37
  • 1
    The syntax wouldn't change at all, just like you can say `a + b` no matter if `operator+` is a member function or a free function. – fredoverflow Mar 04 '11 at 13:25
  • @FredOverflow: There's a world of difference. `operator+` is a binary argument operator. `operator[]` is an unary operator. `operator+` intends that a calculation be made with both arguments, the idea of an invoking object is inapproriate. `operator[]` suggests than object is accessing/searching/finding something based on the argument passed in. Writing `[vector, 2]` to access the object at index 2 in vector is syntactically very different than writing `vector[2]`. – Sion Sheevok Mar 04 '11 at 13:31
  • The syntax would be as in my answer, with 2 parameters – CashCow Mar 04 '11 at 13:34
  • @CashCow: That's the declaration syntax, how about the syntax for using it? If it uses the same old syntax, then that suggests that a user can define how a container should access it's own data, since it allows the user to write an `operator[]` for a class they did not write. That makes sense for `operator<<` and `operator>>` which are intended for insertion and extraction of data, data which may be of a user created type, but not for accessing contained, private, internal data. – Sion Sheevok Mar 04 '11 at 13:36
  • 1
    Clearly, the expression `a[b]` has two operands, and there is no reason why one should not be able define a free function `E& operator[](T& container, size_t index)` that is called via `container[index]` syntax. – fredoverflow Mar 04 '11 at 13:57
  • @FredOverflow: What then if someone else decides to write `E& operator[](T& container, char Character)`? Later on, someone finds that a call to that function crashes and tries to look up documentation as to why this class is behaving in such a fashion. Eventually, they find out someone externally wrote this broken function. Additionally, how would someone write an external `operator[]` if they are not a friend of the class and can not truly access the class's private members? At best, it would work as some sort of wrapper for calling the class's `operator[]` with different parameter types. – Sion Sheevok Mar 04 '11 at 14:02
  • Those are all very good points, however they have nothing to do with the syntax issue that I opposed to ;) – fredoverflow Mar 04 '11 at 14:35
  • @Sion: We actually have both unary and binary versions of operator+. Could just as well have had that for operator[] as well. – Bo Persson Mar 04 '11 at 17:17