[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

const correctness - should C++ prefer const member over non-const?

fungus

10/30/2008 5:13:00 AM

I define this class:


class foo {
std::vector<int>data;
public:

int operator[](int n) {
return data[n];
}
int operator[](int n) const {
return data[n];
}
};


Now in my program I do:

foo myFoo;
int x = myFoo[123];
....


Should the const version of foo::operator[] be called?

I think it should, but my compiler disagrees with me.

What's the correct behavior? Why...?



--
<\___/>
/ O O \_____/ FTB.

http://www.to... - New 3D editor!
19 Answers

blargg.h4g

10/30/2008 5:31:00 AM

0

In article
<7908dabe-5102-4669-bf68-6cd36bedd6a7@m74g2000hsh.googlegroups.com>,
fungus <openglMYSOCKS@artlum.com> wrote:

> I define this class:
>
>
> class foo {
> std::vector<int>data;
> public:
>
> int operator[](int n) {
> return data[n];
> }
> int operator[](int n) const {
> return data[n];
> }
> };
>
>
> Now in my program I do:
>
> foo myFoo;
> int x = myFoo[123];
> ...
>
>
> Should the const version of foo::operator[] be called?
>
> I think it should, but my compiler disagrees with me.
>
> What's the correct behavior? Why...?

I'm interested in why you think it should call the const version. If it
did, when would it ever call the non-const version?

Jerry Coffin

10/30/2008 5:42:00 AM

0

In article <7908dabe-5102-4669-bf68-6cd36bedd6a7
@m74g2000hsh.googlegroups.com>, openglMYSOCKS@artlum.com says...
> I define this class:
>
>
> class foo {
> std::vector<int>data;
> public:
>
> int operator[](int n) {
> return data[n];
> }
> int operator[](int n) const {
> return data[n];
> }
> };
>
>
> Now in my program I do:
>
> foo myFoo;
> int x = myFoo[123];
> ...
>
>
> Should the const version of foo::operator[] be called?

No.

> I think it should, but my compiler disagrees with me.

The compiler's right. The const version should be called for a const
object. The non-const version should be called for a non-const object.
If you don't/didn't have a non-const version, then the const version
could be called -- but it would be called by convertion the non-const to
a const object first. That's fine (in this case) but it's still a
conversion. When matching overloaded functions, one that doesn't require
a conversion is a better match than one that does require a conversion.

Most people want the const version used on the RHS of an assignment, but
the non-const for the LHS. To get what that kind of behavior, you
normally use a proxy object that overloads operator= and operator T.

--
Later,
Jerry.

The universe is a figment of its own imagination.

fungus

10/30/2008 9:22:00 AM

0

On Oct 30, 6:31 am, blargg....@gishpuppy.com (blargg) wrote:
>
> I'm interested in why you think it should call the const version. If it
> did, when would it ever call the non-const version?

Ok, maybe I oversimplified it. Supposed operator[]
returns a reference to the int:

int& operator[](int n) {
return data[n];
}
int& operator[](int n) const {
return data[n];
}

If the expression is on the RHS of an assignment, should
the const version be called?


--
<\___/>
/ O O \_____/ FTB.

http://www.to... - New 3D editor!

fungus

10/30/2008 9:27:00 AM

0

On Oct 30, 10:21 am, fungus <openglMYSO...@artlum.com> wrote:
>
> Ok, maybe I oversimplified it. Supposed operator[]
> returns a reference to the int:
>

....and just before the pedants arrive, suppose it's
a struct not an int, and I want to access a member
of the stuct.

my_struct& operator[](int n) { return data[n]; }
const my_struct& operator[](int n) const { return data[n]; }

Why does the compiler choose the non-const version
for the RHS of an expression...?


--
<\___/>
/ O O \_____/ FTB.

http://www.to... - New 3D editor!

anon

10/30/2008 9:41:00 AM

0

fungus wrote:
> I define this class:
>
>
> class foo {
> std::vector<int>data;
> public:
>
> int operator[](int n) {
> return data[n];

Changing this line to this:
return data.at(n);
is much safer

> }
> int operator[](int n) const {
> return data[n];
> }
> };
>
>
> Now in my program I do:
>
> foo myFoo;
> int x = myFoo[123];
> ...
>

This should call the non-const operator[]

If you had:
const foo myFoo;
int x = myFoo[123];
then the const version of the operator[] would be used

>
> Should the const version of foo::operator[] be called?
>
> I think it should, but my compiler disagrees with me.
>
> What's the correct behavior? Why...?
>

anon

10/30/2008 9:43:00 AM

0

fungus wrote:
> On Oct 30, 10:21 am, fungus <openglMYSO...@artlum.com> wrote:
>> Ok, maybe I oversimplified it. Supposed operator[]
>> returns a reference to the int:
>>
>
> ...and just before the pedants arrive, suppose it's
> a struct not an int, and I want to access a member
> of the stuct.
>
> my_struct& operator[](int n) { return data[n]; }
> const my_struct& operator[](int n) const { return data[n]; }
>
> Why does the compiler choose the non-const version
> for the RHS of an expression...?

Because your myFoo object is not const

fungus

10/30/2008 10:00:00 AM

0

On Oct 30, 6:41 am, Jerry Coffin <jcof...@taeus.com> wrote:
>
> > Should the const version of foo::operator[] be called?
>
> No.
>
> > I think it should, but my compiler disagrees with me.
>
> The compiler's right.

Bummer. I've got an object which triggers quite
a big internal rebuild when you call the non-const
version and I just noticed it's doing a lot of
rebuilding because of this assumption.


--
<\___/>
/ O O \_____/ FTB.

http://www.to... - New 3D editor!

SG

10/30/2008 10:29:00 AM

0

On 30 Okt., 10:59, fungus <openglMYSO...@artlum.com> wrote:
> Bummer. I've got an object which triggers quite
> a big internal rebuild when you call the non-const
> version and I just noticed it's doing a lot of
> rebuilding because of this assumption.

You can explicitly convert your object to a const version if you don't
want the non-const member function to be called in some cases:

const foo& myConstFoo = myFoo;
int blah = myConstFoo[42];

or something like that. static_cast<foo const&>(myFoo)[42] should also
work as far as I can tell. Though, these kinds of casts are still a
bit of a mystery to me.

Cheers,
SG

blargg.h4g

10/30/2008 10:42:00 AM

0

In article
<8141ce63-f45b-4692-a05b-e6c44b367c7c@e17g2000hsg.googlegroups.com>,
fungus <openglMYSOCKS@artlum.com> wrote:

> On Oct 30, 10:21=A0am, fungus <openglMYSO...@artlum.com> wrote:
> >
> > Ok, maybe I oversimplified it. Supposed operator[]
> > returns a reference to the int:
>
> ...and just before the pedants arrive, suppose it's
> a struct not an int, and I want to access a member
> of the stuct.
>
> my_struct& operator[](int n) { return data[n]; }
> const my_struct& operator[](int n) const { return data[n]; }
>
> Why does the compiler choose the non-const version
> for the RHS of an expression...?

That's a better question. It chooses the non-const version because C++
doesn't overload based on return type or how the caller uses the return
value, only arguments to the function (including the implicit "this"
argument to member functions). I could have sworn "The Design and
Evolution of C++" covered the reason behind this, but I couldn't find a
reference. I'm assuming it would complicate overloading and often not be
desired.

blargg.h4g

10/30/2008 10:45:00 AM

0

In article
<bc2244bc-58cd-4e4e-bf20-3c66f04a4bb4@b1g2000hsg.googlegroups.com>, SG
<s.gesemann@gmail.com> wrote:

> On 30 Okt., 10:59, fungus <openglMYSO...@artlum.com> wrote:
> > Bummer. I've got an object which triggers quite
> > a big internal rebuild when you call the non-const
> > version and I just noticed it's doing a lot of
> > rebuilding because of this assumption.
>
> You can explicitly convert your object to a const version if you don't
> want the non-const member function to be called in some cases:
>
> const foo& myConstFoo = myFoo;
> int blah = myConstFoo[42];

But you can't expect users of the class to do this consistently, since
it's quite tedious. Even having a named T& modify( int index ) would be
better. As others have mentioned, a proxy object with an operator T () and
operator = ( T const& ) would be most transparent to the user.