const and non-const operator[] Vs. lvalue and rvalue use

M

Mark Stijnman

I would like to be able to have an object accessible as a vector using
the [] operator, but able to track modifications to its data, so that
it can update other internal data as needed. I figured that setting a
flag in the non-const operator[] would work, but it doesn't. Take the
code below:

#include <iostream>

using std::cout;
using std::cerr;
using std::endl;

class Test {
public:
Test() {
for (int i=0; i<4; i++) t = 1.0;
}

const double& operator[](const unsigned index) const {
cerr << "const operator called" << endl;
return t[index];
}
double& operator[](const unsigned index) {
cerr << "non-const operator called" << endl;
return t[index];
}
private:
double t[4];
};

int main() {
Test t;

t[2] = 2; // #1
cout << "t[2] = " << t[2] << endl; // #2
t[3] += t[2] + t[1]; // #3
cout << "t[3] = " << t[3] << endl; // #4
}

I personally expected it to use the non-const version in the lines
marked #1 and #3, where it uses t as an lvalue, and use the const
version when t is used as an rvalue, like in lines #2, the right
hand side of #3, and in line #4. Unfortunately, on my system, when run,
it appears only the non-const operator gets called. Apparantly that's
not how it works. How are the rules here defined? And how do I get the
behaviour I want (i.e., different versions called, depending on use as
an lvalue or not)?

regards Mark
 
V

Victor Bazarov

Mark said:
I would like to be able to have an object accessible as a vector using
the [] operator, but able to track modifications to its data, so that
it can update other internal data as needed. I figured that setting a
flag in the non-const operator[] would work, but it doesn't. Take the
code below:

#include <iostream>

using std::cout;
using std::cerr;
using std::endl;

class Test {
public:
Test() {
for (int i=0; i<4; i++) t = 1.0;
}

const double& operator[](const unsigned index) const {
cerr << "const operator called" << endl;
return t[index];
}
double& operator[](const unsigned index) {
cerr << "non-const operator called" << endl;
return t[index];
}
private:
double t[4];
};

int main() {
Test t;

t[2] = 2; // #1
cout << "t[2] = " << t[2] << endl; // #2
t[3] += t[2] + t[1]; // #3
cout << "t[3] = " << t[3] << endl; // #4
}

I personally expected it to use the non-const version in the lines
marked #1 and #3, where it uses t as an lvalue, and use the const
version when t is used as an rvalue, like in lines #2, the right
hand side of #3, and in line #4. Unfortunately, on my system, when run,
it appears only the non-const operator gets called. Apparantly that's
not how it works. How are the rules here defined?


That's extremely simple. 't' (for which operator[] is called) is not
a const object. For a non-const object a non-const version is called.
And how do I get the
behaviour I want (i.e., different versions called, depending on use as
an lvalue or not)?

You can't (not easily, anyway). The return value type is not the deciding
factor in the process of picking which overloaded function to call.

V
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Mark said:
I would like to be able to have an object accessible as a vector using
the [] operator, but able to track modifications to its data, so that
it can update other internal data as needed. I figured that setting a
flag in the non-const operator[] would work, but it doesn't. Take the

You can return some type of proxy object in the non const operator [ ], and
in this object have an operator = that sets the modified flag corresponding
to the item it refers to.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top