Hi all,
In an SDK I found a class with two operator[] functions, which are both the same except for the addition of const in one of them.:
1 2
charoperator [] ( int i );
constcharoperator [] ( int i ) const;
I know the use of one const operator[] returning a value and another operator[] returning a reference. But these both return a value.
I can do char a = Obj[0]; and get a value. I cannot do Obj[0] = a;, which (understandably) gives me the error
left operand must be l-value
What is the use of having both of these operator[]'s?
Actually none of them returns a reference. Unless you return a reference you cannot edit it. They are BOTH a copied value, none of them is an address.
There are three kind of things for this:
Original Value
Copied Value
Pointer to Original Value
Let me distinguish them:
1 2 3 4 5 6 7 8 9
// char* -> Pointer to Original Value, You shouldn't use this for operator[] most times
charoperator[] (int i); // Copied Value. You'll see the difference within a minute
char& operator[] (int i); // Original Value. You see the '&' ? It means the
// original value will not be copied and you will be able to do Obj[0] = a;
// You should:
char& operator[] ( int i );
constchar& operator[] ( int i ) const; // also remember to edit the definitions.
Yeah I just noticed your editing from Pointer to Reference, sorry.
There is no any sense in declaring such overload operators because return values char and const char are equivalent. So it would be better to declare one operator
char operator []( int i ) const;
Usually the subscript operator are overloaded the following way
char operator []( int i ) const;
char & operator []( int i );
Still puzzled! Your answers are exactly what I already knew. The more I do not understand why an SDK would write two exact same functions (except for one has const) without there being any use for it.
There must be a situation in which this is useful. I looked at the standard and it doesn't mention anything about the need for a const operator[] and a non-const operator [], so it is absolutely not required. When I hover over it in Visual Studio, I can see both declarations - whether I use it as an rvalue (which works) or as lvalue (which obviously doesn't work).
You are wrong that there is no need to declare const and non-const operators. If you have a const object then you can use only a const method. For example
1 2 3
const MyClass obj;
char c = obj[0]; // here the const method is called.
Or another example
1 2 3 4
void f( const MyClass &obj )
{
char c = obj[0]; // here again the const method is called
}
The point is that there is no any sense to declare return type as char and const char.
Clear, but by "need" I meant "required by the standard".
Maybe the reason for the two functions in my original question is that the non-const or the const can be used for general object as rvalue, and the specifically const is added to accommodate the use (again as rvalue) on const objects.
If you're asking about the code in your original post (where both return by value)... then there is no point. That code is broken at worst, or wasteful at best. The non-const version can be thrown away entirely without losing any functionality.
However if you're asking about the more TYPICAL code, where the non-const version returns a reference and the const version returns a const reference (or value):
1 2
char& operator [] ( int i ); // this makes sense now
constchar& operator [] ( int i ) const; // the & here may be omitted
These functions now serve two very different purposes. The non-const version allows for l-value assignment with non-const objects. Whereas the const version allows for r-value usage with const objects:
1 2 3 4 5 6 7 8 9 10 11
const YourClass c; // c is const
YourClass nc; // nc is non-const
c[0]; // uses the 'const' version
nc[0]; // uses the 'non-const' version
c[0] = 5; // ERROR - const version returns a const reference.. can't assign to a const reference
foo = c[0]; // OK
nc[0] = 5; // OK - non-const version allows assignment
foo = nc[0]; // also OK
Hi Disch,
I am sorry for not being clear enough. I meant the two operator[] functions in my original code returning values. My last post was a bit silly indeed. (An rvalue is always treaded as constant as far as I understand.)
Note that this link shows SDK version 8. The current SDK version is 12 and has exactly the same QuadChar class, so the operator[] functions have stayed for quite a while.
(The QuadChar [a container for four chars] is stored externally and created and accessed through a QuadCharAutoPtr object.) Calling the operator[] is done like this:
1 2
fmx::QuadCharAutoPtr QAP( 'a', 'b', 'c', 'd' );
char a = (*QAP)[2]; // a = 'c'
Well that is a programmer mistake then.
They are not useful at all, completely useless.
You can only copy a character to another variable in that way, but you won't be able to modify the character using the same way.
Thanks for the confirmation. I thought I lacked some knowledge about operators[], but it appears not to be my lack of understanding, but rather a piece of obscure code.