473,395 Members | 1,791 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,395 software developers and data experts.

Why does reading from a std::map not considered const?

Why does reading a member of a std::map not considered const? For example:

class My_Class
{
int Get_Map_Value( int index ) const // ** error ** not considered
const!!!
{
return m_Map[index] ; // note that m_Map is not changed, only read
from
}
std::map<int,int> m_Map ;
} ;

This really reeks havoc when to try to use const for its intended purpose...

[==Peteroid==]

PS - I'm using MS VC++.NET and creating a Managed C++ application, if that
matters...
Nov 17 '05 #1
13 1417
Peteroid wrote:
Why does reading a member of a std::map not considered const? For example:

class My_Class
{
int Get_Map_Value( int index ) const // ** error ** not considered
const!!!
{
return m_Map[index] ; // note that m_Map is not changed, only read
from
}
std::map<int,int> m_Map ;
} ;

This really reeks havoc when to try to use const for its intended purpose...

[==Peteroid==]

PS - I'm using MS VC++.NET and creating a Managed C++ application, if that
matters...


If the key isn't already present in the map, map::operator[] will create a
new (K,V) pair and store it in the map, returning the V part by reference.
(Use of this operator requires the mapped_type be default-constructible.)

You can avoid this behavior by using map::find, though your function as
specified above will either have to return a default value or throw an
exception if that function returns end().

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #2
So, if I get you right, using operator[] on a std::map isn't const because
of the POSSIBILITY it might give be given a key not already in the map.
Thus, even if my code insures I won't ever ask for an entry for which a key
doesn't already exist, it can't be declared const since I might not write
good code in this regard.

I believe I now understand, but feel it should have been the case that
operator[] was designed to allow const and to just cause an error if a
request for an entry where no key existed was asked for, and force people to
check on existence using the count() method (which returns 0 if the entry
doesn't exist and 1 if it does). That is, treat it much like trying to
access an array element that is out of bounds...

Thanks Doug!

[==Peteroid==]

"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:cr********************************@4ax.com...
Peteroid wrote:
Why does reading a member of a std::map not considered const? For example:
class My_Class
{
int Get_Map_Value( int index ) const // ** error ** not considered
const!!!
{
return m_Map[index] ; // note that m_Map is not changed, only read
from
}
std::map<int,int> m_Map ;
} ;

This really reeks havoc when to try to use const for its intended purpose...
[==Peteroid==]

PS - I'm using MS VC++.NET and creating a Managed C++ application, if thatmatters...


If the key isn't already present in the map, map::operator[] will create a
new (K,V) pair and store it in the map, returning the V part by reference.
(Use of this operator requires the mapped_type be default-constructible.)

You can avoid this behavior by using map::find, though your function as
specified above will either have to return a default value or throw an
exception if that function returns end().

--
Doug Harrison
Microsoft MVP - Visual C++

Nov 17 '05 #3
Peteroid wrote:

So, if I get you right, using operator[] on a std::map isn't const because
of the POSSIBILITY it might give be given a key not already in the map.
Thus, even if my code insures I won't ever ask for an entry for which a key
doesn't already exist, it can't be declared const since I might not write
good code in this regard.

I believe I now understand, but feel it should have been the case that
operator[] was designed to allow const and to just cause an error if a
request for an entry where no key existed was asked for, and force people to
check on existence using the count() method (which returns 0 if the entry
doesn't exist and 1 if it does). That is, treat it much like trying to
access an array element that is out of bounds...


const is an abortion in C++.

In theory, it sounds like a good idea. In practice, it just doesn't work.
Nov 17 '05 #4
Peteroid wrote:
So, if I get you right, using operator[] on a std::map isn't const because
of the POSSIBILITY it might give be given a key not already in the map.
Thus, even if my code insures I won't ever ask for an entry for which a key
doesn't already exist, it can't be declared const since I might not write
good code in this regard.
I wouldn't necessarily characterize this as a "good code" issue. To provide
the non-const operator[], std::map has to be able to deal with:

m[k] = t;

for some k not already in the map. It would be subtle for the non-const
operator[] to add items but for const operator[] to throw for items that
don't already exist in the map.
I believe I now understand, but feel it should have been the case that
operator[] was designed to allow const and to just cause an error if a
request for an entry where no key existed was asked for, and force people to
check on existence using the count() method (which returns 0 if the entry
doesn't exist and 1 if it does). That is, treat it much like trying to
access an array element that is out of bounds...
I guess they figured that operator[] shouldn't change in definedness
depending on const vs. non-const, though the standard library isn't entirely
consistent with that philosophy. In any case, you can write your own indexer
functions that throw for items not already in the map, at some loss of
notational convenience. (Think vector::at, but as a non-member "lookup(m,
k)" or something...)

(Speaking of gotchas, note also that an insert() that finds the key doesn't
update the item already in the map. That got me once...)
Thanks Doug!


No problem.

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #5
> const is an abortion in C++.
In theory, it sounds like a good idea.
In practice, it just doesn't work.


At the risk of starting a 'religous war', const is one of those 'road
blocks' we throw into our own programming path to make sure we don't
accidentally fall off a cliff. Another such road block is 'private'. You
could always define everything in a class to be 'public'. In fact, any code
that works will still work if 'private' is replaced by 'protected' or
'public'. However, 'private' prevents outside forces from changing such
variables without going through the mechanisms provided by the class. This
encapsulates the class so that it will perform more like a self-contained
object than merely a convenient and organizational combinantion of code and
data.

In the case of 'const' this allows programmers to insure that a class method
does not actually change anything in the class. In effect, it makes sure
that those methods you intend to be 'read-only' in nature with respect to
the class, are indeed, living up to that promise. It therefore acts as a way
of programming with a particualr style or mindset (a paradigm if you will),
to help find problems in dis-functioning code (via visual elimination of
methods that couldn't possibly change class members), and as a guard dog to
prevent conception errors at compile time.

I tend to use 'const' whenever I can. But, like I occasional must demote
(promote? guess it depends on your pov) 'private' to 'protected' (like when
it is faster and/or makes more sense for a child to have direct access than
to have to go through a 'property' method of the parent), sometimes I find I
must remove the 'const', simply because I realize it only changes an
un-important part of the class (such as a temporary convenience variable),
or as this thread is about, I'm using a standard template library container
which looks like it should act const, but in fact is not.

And, as you can see, I'm more than happy to construct run-on sentences to
make my points...lol

[==Peteroid==]
Nov 17 '05 #6
Bret Pehrson <br**@classicade.com> wrote:
[...]

const is an abortion in C++.

In theory, it sounds like a good idea. In practice, it just doesn't work.

I have used to for ten years and it
has proven to be very useful to me.

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett
Nov 17 '05 #7
Peteroid wrote:
const is an abortion in C++.
In theory, it sounds like a good idea.
In practice, it just doesn't work.


At the risk of starting a 'religous war', const is one of those 'road
blocks' we throw into our own programming path to make sure we don't
accidentally fall off a cliff...


Yes, I know what const is for, and where and when appropriate.

The problem, as I said, that in practice, it just doesn't work. I'll
elaborate: If working on any medium scale+ project where there are more than a
few programmers and you use either a packaged framework and/or external C++
libraries, you quickly run into const problems.

You and your crew may do a great job of using const in the appropriate cases,
but if you reference something else that doesn't, then you are at an impasse --
you must either use some disgusting cast to cast away const or modify your own
code to remove const, even though your code is correct.

_This_ is what I mean when I say in practice, it doesn't work. Like Hendrik,
I've used const for more than 10 years, and in my own code projects or other
similar small projects, const is just fine. However, in just about every other
large scale case, const in my/our code has led to problems, issues, and
eventual removal because one or more of our third party libraries chose to
implement a particular method that should have been const but wasn't.

My casual thoughts (i.e. I haven't thought through it in any detail) is that
class methods should be _const_by_default_ and specifically de-const'd
where/when appropriate.
Nov 17 '05 #8
Bret Pehrson wrote:
My casual thoughts (i.e. I haven't thought through it in any detail) is that
class methods should be _const_by_default_ and specifically de-const'd
where/when appropriate.


That would take some getting used to, but it's consistent with the current
fad(?) of explicitly granting privileges.

I think I'd genuinely like it applied to function parameters, most of which
should be declared const, and most of which rarely are. I'm speaking of
course about top-level const, e.g.

// What user should see:
void f(int x);
void g(char* x);

// What implementations normally would benefit from:
void f(int const x) {...}
void g(char* const x) {...}

You can do this already, of course, but it's a pain, and most people skip
it, even though they may diligently declare local variables const.

While we're at it, let's disable copying of classes by default.

And fix the casual approach to overriding virtual functions, which is prone
to accident.

Anything else? :)

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #9
"Doug Harrison [MVP]" wrote:

Bret Pehrson wrote:
My casual thoughts (i.e. I haven't thought through it in any detail) is that
class methods should be _const_by_default_ and specifically de-const'd
where/when appropriate.


That would take some getting used to, but it's consistent with the current
fad(?) of explicitly granting privileges.

I think I'd genuinely like it applied to function parameters, most of which
should be declared const, and most of which rarely are. I'm speaking of
course about top-level const, e.g.

// What user should see:
void f(int x);
void g(char* x);

// What implementations normally would benefit from:
void f(int const x) {...}
void g(char* const x) {...}

You can do this already, of course, but it's a pain, and most people skip
it, even though they may diligently declare local variables const.

While we're at it, let's disable copying of classes by default.

And fix the casual approach to overriding virtual functions, which is prone
to accident.

Anything else? :)


Except for the const stuff, looks a lot like C#...
Nov 17 '05 #10
Doug Harrison [MVP] <ds*@mvps.org> wrote:
[...]

You can do this already, of course, but it's a pain, and most people skip
it, even though they may diligently declare local variables const.

While we're at it, let's disable copying of classes by default.

And fix the casual approach to overriding virtual functions, which is prone
to accident.

Anything else? :)

Make one-arg ctors explicit by default.

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett
Nov 17 '05 #11
Bret Pehrson <br**@classicade.com> wrote:
[...]

Yes, I know what const is for, and where and when appropriate.

The problem, as I said, that in practice, it just doesn't work. I'll
elaborate: If working on any medium scale+ project where there are more than a
few programmers and you use either a packaged framework and/or external C++
libraries, you quickly run into const problems.

You and your crew may do a great job of using const in the appropriate cases,
but if you reference something else that doesn't, then you are at an impasse --
you must either use some disgusting cast to cast away const or modify your own
code to remove const, even though your code is correct.
If there are ugly corners that you can
not fix, isolate them using casts or by
passing temporaries as arguments etc.
_This_ is what I mean when I say in practice, it doesn't work. Like Hendrik,
I've used const for more than 10 years, and in my own code projects or other
similar small projects, const is just fine. However, in just about every other
large scale case, const in my/our code has led to problems, issues, and
eventual removal because one or more of our third party libraries chose to
implement a particular method that should have been const but wasn't.
I don't think I ever have /removed/ a
'const' that should be there due to
some other code getting it wrong.
However, I have spent whole days on
some projects just because I wanted
to /add/ 'const' to some function that
should have had it already but failed
and that resulted in many other cases
where a 'const' was missing. IIRC,
there wasn't a single case where this
did not discover a bug in the code
base. Those that shook their heads
when I "wasted" hours on this often
soon were busy fixing the bugs found
this way.
My casual thoughts (i.e. I haven't thought through it in any detail) is that
class methods should be _const_by_default_ and specifically de-const'd
where/when appropriate.


Not bad an idea. But I think there
are a few more important cases where
the default behaviour should be
changed to the opposit.

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett
Nov 17 '05 #12
Hendrik Schober <Sp******@gmx.de> wrote:
[...]

You can do this already, of course, but it's a pain, and most people skip
it, even though they may diligently declare local variables const.

While we're at it, let's disable copying of classes by default.

And fix the casual approach to overriding virtual functions, which is prone
to accident.

Anything else? :)


Make one-arg ctors explicit by default.


Oh, and automagically insert 'break'
statements before each 'case'. (Or
however it's done -- I don't care.
It's just that even after a dozen
years of C/C++ I still forget this
damn 'break' once in a while. OTOH,
I rarely ever want to fall through
to the next label.)

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett
Nov 17 '05 #13
>>Oh, and automagically insert 'break'
statements before each 'case'. (Or
however it's done -- I don't care. ..>>It's just that even after a dozenyears of C/C++ I still forget this
damn 'break' once in a while. OTOH,
I rarely ever want to fall through
..>>to the next label.)

I agree! I often fall into that (rookie?) trap when using 'switch'. Maybe
there should be two compiler directives to make either 'with break' or
'without break' the default in 'case' blocks ('without break' is the way it
is hard-wired now), and the addition of an 'unbreak' ('continue'?) to
override the default of 'break'.

Or, two 'switch's: 'switch' is as it is now (for compatibility), while
'switch_with_break' is a new one.

[==Peteroid==]

"Hendrik Schober" <Sp******@gmx.de> wrote in message
news:el**************@TK2MSFTNGP09.phx.gbl... Hendrik Schober <Sp******@gmx.de> wrote:
[...]

You can do this already, of course, but it's a pain, and most people skip it, even though they may diligently declare local variables const.

While we're at it, let's disable copying of classes by default.

And fix the casual approach to overriding virtual functions, which is prone to accident.

Anything else? :)


Make one-arg ctors explicit by default.


Oh, and automagically insert 'break'
statements before each 'case'. (Or
however it's done -- I don't care.
It's just that even after a dozen
years of C/C++ I still forget this
damn 'break' once in a while. OTOH,
I rarely ever want to fall through
to the next label.)

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The presence of those seeking the truth is infinitely
to be prefered to those thinking they've found it."
Terry Pratchett

Nov 17 '05 #14

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

Similar topics

24
by: Duane Hebert | last post by:
2 questions: Given a map defined as std::map<int,string> stringmap; //How do you access the data_type (string) via an iterator? std::string spoo("doh");
8
by: Kin Pang | last post by:
Hi, I have a routine where I'm using a std::map from a pair of ints to double for caching evaluation results. The cache depth could be upto say 1000 in depth. However, my application needs to...
5
by: cppaddict | last post by:
Hi, I'm confused about what the comparison operator in a map template is: In particular, I want to know why something like the following doesn't work: bool pointCompare(POINT p1, POINT p2)...
4
by: Grey Plastic | last post by:
I do not understand why this code fails to compile (under gcc): #include <map> using namespace std; class Foo { map<Foo*,int> myMap; public: int lookup(const Foo& f) const { myMap.find(&f);...
1
by: Bob | last post by:
Hi, I'm trying to use a map with a string key, and a pointer to objects contained in a vector. I've wrapped this in a class like so: // cMap template<class T> class cMap : public cList<T> { ...
2
by: Serengeti | last post by:
Hello, in my class I have a map that translates strings to pointers to some member functions. The code goes like this: class F { typedef void (Function::*MathFuncPtr)(); std::map<std::string,...
1
by: Saeed Amrollahi | last post by:
Dear All C++ Programmers Hello I am Saeed Amrollahi. I am a software engineer in Tehran Sewerage Company. I try to use std::map and map::find member function. I use Visual Studio .NET. my...
2
by: mergaite_lietuvaite | last post by:
Hi, I try to use map. My code is very easy, but there are some errors.... (by compiling). Plaese, could you say, what I do wrong.. struct less_array { bool operator()(const FArray p1, const...
7
by: guido | last post by:
Hi, I'm looking for a container class that can map whole ranges of keys to objects - something like std::map, but not only for individual values for the key, but for whole ranges. Example: I...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.