473,320 Members | 2,110 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

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

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.topaz3d.com/ - New 3D editor!
Oct 30 '08 #1
19 2668
In article
<79**********************************@m74g2000hsh. googlegroups.com>,
fungus <op***********@artlum.comwrote:
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?
Oct 30 '08 #2
In article <7908dabe-5102-4669-bf68-6cd36bedd6a7
@m74g2000hsh.googlegroups.com>, op***********@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.
Oct 30 '08 #3
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.topaz3d.com/ - New 3D editor!
Oct 30 '08 #4
On Oct 30, 10:21*am, fungus <openglMYSO...@artlum.comwrote:
>
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.topaz3d.com/ - New 3D editor!

Oct 30 '08 #5
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...?
Oct 30 '08 #6
fungus wrote:
On Oct 30, 10:21 am, fungus <openglMYSO...@artlum.comwrote:
>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
Oct 30 '08 #7
On Oct 30, 6:41*am, Jerry Coffin <jcof...@taeus.comwrote:
>
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.topaz3d.com/ - New 3D editor!
Oct 30 '08 #8
SG
On 30 Okt., 10:59, fungus <openglMYSO...@artlum.comwrote:
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
Oct 30 '08 #9
In article
<81**********************************@e17g2000hsg. googlegroups.com>,
fungus <op***********@artlum.comwrote:
On Oct 30, 10:21=A0am, fungus <openglMYSO...@artlum.comwrote:

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.
Oct 30 '08 #10
In article
<bc**********************************@b1g2000hsg.g ooglegroups.com>, SG
<s.********@gmail.comwrote:
On 30 Okt., 10:59, fungus <openglMYSO...@artlum.comwrote:
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.
Oct 30 '08 #11
On Oct 30, 11:41*am, blargg....@gishpuppy.com (blargg) wrote:
I could have sworn "The Design and Evolution of C++"
covered the reason behind this, but I couldn't find a
reference.
Maybe you mean section 3.7.1 ?
--
<\___/>
/ O O \
\_____/ FTB.

http://www.topaz3d.com/ - New 3D editor!

Oct 30 '08 #12
On Oct 30, 11:45*am, blargg....@gishpuppy.com (blargg) wrote:
As others have mentioned, a proxy object with an operator T () and
operator = ( T const& ) would be most transparent to the user.
I don't see how that works for a struct...

I want operator[] to return a reference to a struct
and be able to do this:

Foo f = myStuff[i].foo;

and

myStuff[i].foo = f;
With the first one calling the const version of operator[].

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

http://www.topaz3d.com/ - New 3D editor!
Oct 30 '08 #13
fungus 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.
Then either the two methods' semantics are too different for a
single identifier, or the entity making the offending calls shouldn't
get its hands on a non-const reference, or you should memoize the
rebuilding method.
Martin

--
Quidquid latine scriptum est, altum videtur.
Oct 30 '08 #14
On Oct 30, 1:50*pm, Martin Eisenberg <martin.eisenb...@udo.eduwrote:
the entity making the offending calls shouldn't
get its hands on a non-const reference
This is probably the best solution. I need both const
and non const access inside an event handler function
so I guess I need to make the access more fine-grained.
--
<\___/>
/ O O \
\_____/ FTB.

http://www.topaz3d.com/ - New 3D editor!
Oct 30 '08 #15
On Oct 30, 1:15 pm, fungus <openglMYSO...@artlum.comwrote:
On Oct 30, 11:45 am, blargg....@gishpuppy.com (blargg) wrote:
As others have mentioned, a proxy object with an operator T
() and operator = ( T const& ) would be most transparent to
the user.
I don't see how that works for a struct...
It doesn't, really.
I want operator[] to return a reference to a struct and be
able to do this:
Foo f = myStuff[i].foo;
and
myStuff[i].foo = f;
With the first one calling the const version of operator[].
There are several solutions. The best would be to find a
compiler modified to allow you to overload operator., and use
that. But that sort of ruins portability. Otherwise, you can
overload operator-in the proxy, and tell your users to use
that whenever they do a []---it's ugly and counter-intuitive,
but it works. And for special cases, you can define all of the
members in the proxy, so that they forward to the correct member
of owning class. Or you can just require your clients to get a
reference first, e.g.:
Whatever const& rf = myStuff[ i ].foo
Foo f = rf.foo ;

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 30 '08 #16
In article
<cb**********************************@q9g2000hsb.g ooglegroups.com>, James
Kanze <ja*********@gmail.comwrote:
On Oct 30, 1:15 pm, fungus <openglMYSO...@artlum.comwrote:
[...]
I want operator[] to return a reference to a struct and be
able to do this:

Foo f = myStuff[i].foo;

and

myStuff[i].foo = f;

With the first one calling the const version of operator[].

[...] Or you can just require your clients to get a
reference first, e.g.:

Whatever const& rf = myStuff[ i ].foo
Foo f = rf.foo ;
or

class Stuff {
public:
Whatever const& operator [] ( int ) const;
Whatever& modify( int );
};

void user( Stuff& myStuff )
{
Foo f = myStuff[ i ].foo;
// ...
myStuff.modify( i ).foo = f;
}

If modification is more common than reading, you could instead have [] be
the mutator, and a read( int ) be the accessor.
Oct 31 '08 #17
On Oct 31, 4:46*am, blargg....@gishpuppy.com (blargg) wrote:
>
* * class Stuff {
* * public:
* * * * Whatever const& operator [] ( int ) const;
* * * * Whatever& modify( int );
* * };

* * void user( Stuff& myStuff )
* * {
* * * * Foo f = myStuff[ i ].foo;
* * * * // ...
* * * * myStuff.modify( i ).foo = f;
* * }
This (or variations on it) works too...
--
<\___/>
/ O O \
\_____/ FTB.

http://www.topaz3d.com/ - New 3D editor!

Oct 31 '08 #18
SG wrote:
On 30 Okt., 10:59, fungus <openglMYSO...@artlum.comwrote:
>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.
While I do remember this feeling, this case is rather simple:
You modify 'const', so a 'const_cast' would be what you should
use.
Cheers,
SG
Schobi
Oct 31 '08 #19
anon wrote:
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
I'd be annoyed if I had to use such a 'foo'.
If I want the safe (and slower) variant, I'd want a
'foo::at()' to cal.
[...]
Schobi
Oct 31 '08 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Wenjie | last post by:
Hello, I read someone posted assertions that even the (public) member function is not static, there are probably only one copy of the code in the executable. Then except the...
13
by: Erik Haugen | last post by:
From reading gotw#84 (http://www.gotw.ca/gotw/084.htm), I'm convinced that I should try to make functions nonfriend nonmembers when practical, but then I came across this: Bruce Eckel says about...
4
by: Jian H. Li | last post by:
Hello, What's the essential differences between the two ways of "class::member" & "object.member"(or object_pointer->member)? class C{ public: void f() {} int i; };
12
by: Adrian | last post by:
Could someone please tell me how I can check out the correctness of a site's coding. I have brought about a website, checked it out with various browsers. It seemed to be ok. Then I come across a...
2
by: Clint Olsen | last post by:
Hello: I posted a thread on comp.programming awhile back asking about an algorithm I implemented on square root. The idea was to use the square root of a prime number as a convenient way to get...
2
by: Gabrielle A. Grün | last post by:
Hi All, Does anyone know a way around the illegal reference of a non-static member? Thanks. iNHERITANCE HIERACY
22
by: ypjofficial | last post by:
Is there any possibility of invoking the member functions of a class without creating an object (or even a pointer to ) of that class. eg. #include <iostream.h> class test { public: void...
11
by: ziman137 | last post by:
Hi all, I have a question here. What is the rationale behind ISO C++ for Static Member Definition? * ISO C++ forbids in-class definition/initialization of non-constant static member...
10
by: shanknbake | last post by:
I'm getting the following compile-time error: error C2352: 'Person::getCount' : illegal call of non-static member function Here is my getCount function declaration:...
24
by: David | last post by:
Hi list. What strategies do you use to ensure correctness of new code? Specifically, if you've just written 100 new lines of Python code, then: 1) How do you test the new code? 2) How do...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.