Modifying the value of key of a map.

M

Milind

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
 
M

Mark P

Milind said:
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
 
S

shailesh

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.
 
K

Kai-Uwe Bux

shailesh said:
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
 
H

homsan toft

Milind said:
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
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top