Page 1 of 1

operator[] ? lvalues!?

Posted: Tue Oct 16, 2007 10:59 pm
by earlz
How can I make an object so that I can go MyObject[5]=93;

it says that operator[] takes exactly 1 argument, so how the crap is it possible?

Re: operator[] ? lvalues!?

Posted: Tue Oct 16, 2007 11:14 pm
by Colonel Kernel
hckr83 wrote:How can I make an object so that I can go MyObject[5]=93;

it says that operator[] takes exactly 1 argument, so how the crap is it possible?
Return a non-const reference to the item that you want to receive the value 93. The 1 argument is the index -- 5 in your example. The assignment happens after operator[] returns.

Re: operator[] ? lvalues!?

Posted: Tue Oct 16, 2007 11:14 pm
by Candy
hckr83 wrote:How can I make an object so that I can go MyObject[5]=93;

it says that operator[] takes exactly 1 argument, so how the crap is it possible?
int &operator[](int index);

Posted: Tue Oct 16, 2007 11:18 pm
by earlz
It doesn't really make sense to me, but it works...so...

Re: operator[] ? lvalues!?

Posted: Tue Oct 16, 2007 11:33 pm
by os64dev
Candy wrote:
hckr83 wrote:How can I make an object so that I can go MyObject[5]=93;

it says that operator[] takes exactly 1 argument, so how the crap is it possible?
int &operator[](int index);
ahum.. because none of the members change it should be:

Code: Select all

int &operator[](int index) const;
:wink:

Re: operator[] ? lvalues!?

Posted: Tue Oct 16, 2007 11:50 pm
by Colonel Kernel
os64dev wrote:
Candy wrote:
hckr83 wrote:How can I make an object so that I can go MyObject[5]=93;

it says that operator[] takes exactly 1 argument, so how the crap is it possible?
int &operator[](int index);
ahum.. because none of the members change it should be:

Code: Select all

int &operator[](int index) const;
:wink:
If you take "const" literally, yes, but it is not always a good idea to do so. Think about the bigger picture. Do you really want to allow code like this?

Code: Select all

const MyClass MyObject; // Should NEVER change!
MyObject[5] = 93; // Whoops, we made operator[] const and let something change...

Posted: Wed Oct 17, 2007 4:34 am
by os64dev
ok but f you take "const" literally, yes, but it is not always a good idea to do so. Think about the bigger picture. Do you really want to allow code like this?

Code: Select all

const MyClass MyObject; // Should NEVER change!
MyObject[5] = 93; // Whoops, we made operator[] and let something change...
maybe i misunderstood but:

Code: Select all

int &operator[](int index) const;
just tells the compiler that this member function does not change the content of the current object and can generate more efficient code. The const here does not specifie a constant return value or a constant object. The code example you gave will not compile.

Posted: Wed Oct 17, 2007 5:36 am
by Solar
os64dev wrote:maybe i misunderstood but:

Code: Select all

int &operator[](int index) const;
just tells the compiler that this member function does not change the content of the current object and can generate more efficient code.
Actually it tells the compiler that this function is valid for const objects. Without the trailing const in the function declaration, a function can only be called for non-const objects.
Colonel Kernel wrote:Do you really want to allow code like this?
Do you really want to disallow code like this (which you would if you did not declare the operator const)?

Code: Select all

const MyClass myObject( ... );
cout << myObject[5];
Depending on the actual semantics of MyClass, you could write something like this to disallow the code you objected to:

Code: Select all

class MyClass {
    public:
        MyClass const & operator[]( int index ) const;
        MyClass & operator[]( int index );
};
That way, the reference returned by operator[]() is const if the MyClass object is const, and non-const otherwise.

Posted: Wed Oct 17, 2007 6:11 am
by os64dev
hmm, it seems i have to re-read the c++ book again.

EDIT: me confused.

constant member function

Posted: Wed Oct 17, 2007 11:37 am
by Colonel Kernel
Solar wrote:Do you really want to disallow code like this (which you would if you did not declare the operator const)?

Code: Select all

const MyClass myObject( ... );
cout << myObject[5];
Of course not.
Depending on the actual semantics of MyClass, you could write something like this to disallow the code you objected to:

Code: Select all

class MyClass {
    public:
        MyClass const & operator[]( int index ) const;
        MyClass & operator[]( int index );
};
That way, the reference returned by operator[]() is const if the MyClass object is const, and non-const otherwise.
Exactly.

Next time I will endeavour to tell more than just half the story. :P

Re: operator[] ? lvalues!?

Posted: Wed Oct 17, 2007 1:29 pm
by Candy
os64dev wrote:ahum.. because none of the members change it should be:

Code: Select all

int &operator[](int index) const;
:wink:
Actually, if you return a reference to a pointer-contained object in this object, this would compile for const objects and be wrong - since you do change the state (or by const-capable actions you perform allow const object visible behaviour to change). Use the method Solar suggested - make two, one for const and one for non-const. Oh, and if you still use MSVC, kick it. VS2005 can't distinguish between const and non-const in at least the copy constructor, so I'm somewhat doubting it can do the other cases.
I refute your attempt to pass MSDN as C++ documentation. Not to mention the non-HTML compatible link.

Posted: Wed Oct 17, 2007 11:56 pm
by os64dev
Oh, and if you still use MSVC, kick it. VS2005 can't distinguish between const and non-const in at least the copy constructor, so I'm somewhat doubting it can do the other cases.
i use a gcc/g++ cross compiler so no issues here
I refute your attempt to pass MSDN as C++ documentation. Not to mention the non-HTML compatible link.
lol

Posted: Thu Oct 18, 2007 1:30 am
by AndrewAPrice
You "could" do it the manual way.

Code: Select all

myObject *myArray;

int NumberOfItems = 5;

myArray[] = new char[NumberOfItems * sizeof(myObject)];
for(int i = 0; i < NumberOfItems; i++)
    myArray[i].myArray(); // call the constructor
then to clean up:

Code: Select all

for(int i = 0; i < NumberOfItems; i++)
    myArray[i].~myArray(); // call the deconstructor
delete myArray;

Posted: Thu Oct 18, 2007 5:25 am
by Candy
MessiahAndrw wrote:You "could" do it the manual way.

Code: Select all

myObject *myArray;

int NumberOfItems = 5;

myArray[] = new char[NumberOfItems * sizeof(myObject)];
for(int i = 0; i < NumberOfItems; i++)
    myArray[i].myArray(); // call the constructor
then to clean up:

Code: Select all

for(int i = 0; i < NumberOfItems; i++)
    myArray[i].~myArray(); // call the deconstructor
delete myArray;
And what exactly, aside from a load of code and a high complexity, does this add over

Code: Select all

myObject myArray[5];
?

Posted: Thu Oct 18, 2007 7:41 am
by AndrewAPrice
In my way you could unwrap the loop that calls the constructors so that each array element can be passed individual constructor parameters.