470,874 Members | 1,789 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,874 developers. It's quick & easy.

Modifying the value of key of a map.

Hi,

I have a map of the type:

std::map<A, B> mymap_A;
std::map<X, A> mymap_X;

where A, B and X are user defined types (i.e. my own clases)

At the beging of the program i do a insert on the maps. Later, at some
point i come across a situation where the value of some member of A
changes. e.g:

class A {
int a_member;
};

when i did an insert a_member was 2; now it is supposed to be 4.

Problem:

my first, and absolutely naive approach was:

std::map<A,B>::iterator i = mymap.find(valueofkey);
i->first = 4;

But this is not allowed as i->first is read only.

Now, the possible solution for this would be to either create a new
pair (and necessarily copy everything in the value part... which is
going to be very costly) and delete old and insert new pair.

Am I missing something too obvious??

Any pointers??

Thnx.
~M

May 30 '06 #1
4 2075
Milind wrote:
Hi,

I have a map of the type:

std::map<A, B> mymap_A;
std::map<X, A> mymap_X;

where A, B and X are user defined types (i.e. my own clases)

At the beging of the program i do a insert on the maps. Later, at some
point i come across a situation where the value of some member of A
changes. e.g:

class A {
int a_member;
};

when i did an insert a_member was 2; now it is supposed to be 4.

Problem:

my first, and absolutely naive approach was:

std::map<A,B>::iterator i = mymap.find(valueofkey);
i->first = 4;

But this is not allowed as i->first is read only.

Now, the possible solution for this would be to either create a new
pair (and necessarily copy everything in the value part... which is
going to be very costly) and delete old and insert new pair.

Am I missing something too obvious??

Any pointers??

Thnx.
~M


The Key type of a map is necessarily a constant. If you want to
"modify" it, the most direct approaches are to delete and re-insert as
you suggested, or use a layer of indirection and let your key have a
pointer to some other data which you can modify freely.

Mark
May 30 '06 #2
How about this?

make the member a_member as mutable. And then modify it through the
iterator.
i->first.a_member = 4;

Or may be through a const member function in class A? This would ensure
that a_member doesn't need to be public.

Just a hack off course.

May 30 '06 #3
shailesh wrote:
How about this?

make the member a_member as mutable. And then modify it through the
iterator.
i->first.a_member = 4;
Please quote. It is hard to know what a_member is without context.
Or may be through a const member function in class A? This would ensure
that a_member doesn't need to be public.

Just a hack off course.


And it may not cut it: we have not been given the details of the classes,
but chances are that a_member takes place in the comparison of keys. If so,
the modification may change the position of this map-entry relative to the
other entries, the map is going to be messed up. In short: you are
modifying a const object and what you earn is undefined behavior.
Best

Kai-Uwe Bux
May 30 '06 #4
Milind wrote:
Hi,

I have a map of the type:

std::map<A, B> mymap_A;
std::map<X, A> mymap_X;

where A, B and X are user defined types (i.e. my own clases)

At the beging of the program i do a insert on the maps. Later, at some
point i come across a situation where the value of some member of A
changes. e.g:

class A {
int a_member;
};

when i did an insert a_member was 2; now it is supposed to be 4.

Problem:

my first, and absolutely naive approach was:

std::map<A,B>::iterator i = mymap.find(valueofkey);
i->first = 4;

But this is not allowed as i->first is read only.

Now, the possible solution for this would be to either create a new
pair (and necessarily copy everything in the value part... which is
going to be very costly) and delete old and insert new pair.

Am I missing something too obvious??


It's hard to tell without looking into your intentions, and perhaps at classes B and X.
Maybe you mixed up the Key and Value parts, or you want something other than a map<A,B>, or...

The basic idea of a map<Key,Value> is that you do (fast) lookup by key,
but you can edit the data freely.
Like
mymap[player.id()].lives--;
or
mymapiter i = mymap.find(player.id()); // mymapiter is supposed to be a (badly named) typedef
if (i != mymap.end()) // if you use find, you must test, otherwise you crash on dereference
i->lives--;

player.id() is the key here. The data is a struct with an int-like member 'lives'.
If you use any other key, you should be looking at other data, ie the data of another player.
And obviously, the id shouldn't change (if it does "id" is probably a bad name for it).
This is what std::maps are supposed to be good for.

If you want to look up by data, eg to find all players with zero lives,
you need something different (perhaps a bidirectional map - is this why you
have both map<A,B> and map<X,A> ? - no way for us to know...)

HTH
homsan
May 30 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by suresh | last post: by
3 posts views Thread by Chris | last post: by
3 posts views Thread by Chris Bingham | last post: by
2 posts views Thread by bandroo | last post: by
6 posts views Thread by tuxedo | last post: by
7 posts views Thread by Ivan Voras | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.