How to delete stl<map> element from iterator?

S

Steve Edwards

Hi,

After making an iterator to a map and stepping through a loop, I want to
delete any entries that satisfy a test from an external function.

MyMapType::const_iterator iter;

for(iter = m->begin(); iter != m->end(); ++iter)
{
a = iter->first;
b = iter->second;
if ( Test(a,b) == true)
iter->delete?();
}

How do I actually delete the element that iter is pointing to?

Thanks

Steve
 
M

Mike Wahler

Steve Edwards said:
Hi,

After making an iterator to a map and stepping through a loop, I want to
delete any entries that satisfy a test from an external function.

MyMapType::const_iterator iter;

for(iter = m->begin(); iter != m->end(); ++iter)

This assumes that 'm' is the name of a pointer to your map,
not of the map itself. I'll keep that assumption below.
{
a = iter->first;
b = iter->second;
if ( Test(a,b) == true)
iter->delete?();
}

How do I actually delete the element that iter is pointing to?

for(iter = m->begin(); iter != m->end(); ++iter)
{
if(condition)
iter = m->erase(iter);
}


An excellent reference for the C++ standard library:
www.josuttis.com/libbook

-Mike
 
V

Victor Bazarov

Steve said:
After making an iterator to a map and stepping through a loop, I want to
delete any entries that satisfy a test from an external function.

MyMapType::const_iterator iter;

for(iter = m->begin(); iter != m->end(); ++iter)
{
a = iter->first;
b = iter->second;
if ( Test(a,b) == true)
iter->delete?();
}

How do I actually delete the element that iter is pointing to?

You ask your map to erase it.

Something like

m->erase(iter);

Beware, though, that after erasing the 'iter' becomes invalid. You cannot
increment it after that. You might want to rewrite your loop like this:

for (.... ; ) // no increment at the end
{
a =
b =
if (..
m->erase(iter++);
else
++iter;
}

V
 
V

Victor Bazarov

Mike said:
if(condition)
iter = m->erase(iter);

IIRC, 'map::erase' has 'void' return type. Some Standard Library
implementations actually violate that to be consistent with other
(sequential) containers, and probably justifiedly, but generally
speaking your code is ill-formed.
}


An excellent reference for the C++ standard library:
www.josuttis.com/libbook

Yep. Check out table 6.31 in it.

V
 
M

Mike Wahler

Victor Bazarov said:
Steve Edwards wrote:

You ask your map to erase it.

Something like

m->erase(iter);

Beware, though, that after erasing the 'iter' becomes invalid. You cannot
increment it after that. You might want to rewrite your loop like this:

Well, I think we both botched our replies. I forgot the
'else' part, and yours disregards the invalid iterator. :)
for (.... ; ) // no increment at the end
{
a =
b =
if (..
m->erase(iter++);

iter = m->erase(iter);
else
++iter;
}

-Mike
 
S

Steve Edwards

Beware, though, that after erasing the 'iter' becomes invalid. You cannot
increment it after that. You might want to rewrite your loop like this:

for (.... ; ) // no increment at the end
{
a =
b =
if (..
m->erase(iter++);
else
++iter;
}

V

Thanks, but sorry, I don't quite understand. If you say the iterator
becomes invalid, should I break at that point. (in which case I haven't
processed all my elements yet.)
On the other hand, I can't continue if the iterator's invalid, can I?

Steve
 
S

Steve Edwards

"Mike Wahler said:
This assumes that 'm' is the name of a pointer to your map,
not of the map itself. I'll keep that assumption below.


for(iter = m->begin(); iter != m->end(); ++iter)
{
if(condition)
iter = m->erase(iter);
}


An excellent reference for the C++ standard library:
www.josuttis.com/libbook

-Mike



Thanks for the link, it's just what I need.

My compiler is complaining about "iter = m->erase(iter);"

(error: no match for 'operator = ')
 
T

TB

Steve Edwards skrev:
Thanks, but sorry, I don't quite understand. If you say the iterator
becomes invalid, should I break at that point. (in which case I haven't
processed all my elements yet.)
On the other hand, I can't continue if the iterator's invalid, can I?

The statement:

iter++;

increments the iterator and returns the previous position. Compare with

int x = 8, y = 0;
y = x++;
// y = 8, x == 9

so the following

m->erase(iter++);

safely erases the desired element and retains a valid iterator pointing
to the next element or m->end().
 
V

Victor Bazarov

Steve said:
Thanks, but sorry, I don't quite understand. If you say the iterator
becomes invalid, should I break at that point. (in which case I haven't
processed all my elements yet.)

Why should you? By passing the value of the post-incremented iterator you
keep it valid. If the 'iter' isn't post-incremented, after 'erase' does
its job, 'iter' cannot be used -- it's invalid. In the proposed code, the
value of 'iter' is passed to 'erase', but _outside_ the object 'iter' is
already pointing to the next element of the map, and therefore is OK.
On the other hand, I can't continue if the iterator's invalid, can I?

No, if it's invalid, you can't. The whole point of using post-increment
is to keep it valid.

V
 
V

Victor Bazarov

Steve said:
[..]
How do I actually delete the element that iter is pointing to?

for(iter = m->begin(); iter != m->end(); ++iter)
{
if(condition)
iter = m->erase(iter);
}
[..]

My compiler is complaining about "iter = m->erase(iter);"

Of course it does. 'm->erase(iter)' returns 'void'. Mike was too hasty
to suggest that solution. It would work for a 'list', for example. It
just doesn't work for 'map'.

V
 
M

Mike Wahler

Victor Bazarov said:
Think again.

OK I did. I see I wasn't thinking before. :)

You've already pointed out my error with this line elsethread.

My excuse is ... we've got a new dog, she ate my attention. :)

-Mike
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top