How to delete stl<map> element from iterator?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steve Edwards

    How to delete stl<map> element from iterator?

    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::cons t_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
  • Mike Wahler

    #2
    Re: How to delete stl&lt;map&gt; element from iterator?


    "Steve Edwards" <gfx@lineone.ne t> wrote in message
    news:gfx-D6FC33.17325521 022006@news.bti nternet.com...[color=blue]
    > 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::cons t_iterator iter;
    >
    > for(iter = m->begin(); iter != m->end(); ++iter)[/color]

    This assumes that 'm' is the name of a pointer to your map,
    not of the map itself. I'll keep that assumption below.
    [color=blue]
    > {
    > 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?[/color]

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


    An excellent reference for the C++ standard library:


    -Mike



    Comment

    • Victor Bazarov

      #3
      Re: How to delete stl&lt;map&gt; element from iterator?

      Steve Edwards wrote:[color=blue]
      > 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::cons t_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?[/color]

      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
      --
      Please remove capital As from my address when replying by mail

      Comment

      • Mike Wahler

        #4
        Re: How to delete stl&lt;map&gt; element from iterator?

        "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message
        news:mrIKf.1333 $a97.1001@newsr ead1.mlpsca01.u s.to.verio.net. ..[color=blue]
        > Steve Edwards wrote:[/color]
        [color=blue][color=green]
        >> How do I actually delete the element that iter is pointing to?[/color]
        >
        > 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:[/color]

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

        iter = m->erase(iter);
        [color=blue]
        > else
        > ++iter;
        > }[/color]

        -Mike


        Comment

        • Victor Bazarov

          #5
          Re: How to delete stl&lt;map&gt; element from iterator?

          Mike Wahler wrote:[color=blue]
          > if(condition)
          > iter = m->erase(iter);[/color]

          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.
          [color=blue]
          > }
          >
          >
          > An excellent reference for the C++ standard library:
          > www.josuttis.com/libbook[/color]

          Yep. Check out table 6.31 in it.

          V
          --
          Please remove capital As from my address when replying by mail

          Comment

          • Victor Bazarov

            #6
            Re: How to delete stl&lt;map&gt; element from iterator?

            Mike Wahler wrote:[color=blue]
            > "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message
            > news:mrIKf.1333 $a97.1001@newsr ead1.mlpsca01.u s.to.verio.net. ..
            >[color=green]
            >>Steve Edwards wrote:[/color]
            >
            >[color=green][color=darkred]
            >>>How do I actually delete the element that iter is pointing to?[/color]
            >>
            >>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:[/color]
            >
            >
            > Well, I think we both botched our replies. I forgot the
            > 'else' part, and yours disregards the invalid iterator. :-)[/color]

            Think again.
            [color=blue]
            >
            >[color=green]
            >> for (.... ; ) // no increment at the end
            >> {
            >> a =
            >> b =
            >> if (..
            >> m->erase(iter++ );[/color]
            >
            >
            > iter = m->erase(iter);
            >
            >[color=green]
            >> else
            >> ++iter;
            >> }[/color]
            >
            >
            > -Mike
            >
            >[/color]


            --
            Please remove capital As from my address when replying by mail

            Comment

            • Steve Edwards

              #7
              Re: How to delete stl&lt;map&gt; element from iterator?

              [color=blue]
              >
              > 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[/color]

              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

              Comment

              • Steve Edwards

                #8
                Re: How to delete stl&lt;map&gt; element from iterator?

                In article <0mIKf.2502$VI6 .433@newsread1. news.pas.earthl ink.net>,
                "Mike Wahler" <mkwahler@mkwah ler.net> wrote:
                [color=blue]
                > "Steve Edwards" <gfx@lineone.ne t> wrote in message
                > news:gfx-D6FC33.17325521 022006@news.bti nternet.com...[color=green]
                > > 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::cons t_iterator iter;
                > >
                > > for(iter = m->begin(); iter != m->end(); ++iter)[/color]
                >
                > This assumes that 'm' is the name of a pointer to your map,
                > not of the map itself. I'll keep that assumption below.
                >[color=green]
                > > {
                > > 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?[/color]
                >
                > 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[/color]



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

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

                (error: no match for 'operator = ')

                Comment

                • TB

                  #9
                  Re: How to delete stl&lt;map&gt; element from iterator?

                  Steve Edwards skrev:[color=blue][color=green]
                  >> 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[/color]
                  >
                  > 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?
                  >[/color]

                  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().

                  --
                  TB @ SWEDEN

                  Comment

                  • Victor Bazarov

                    #10
                    Re: How to delete stl&lt;map&gt; element from iterator?

                    Steve Edwards wrote:[color=blue][color=green]
                    >>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[/color]
                    >
                    >
                    > 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.)[/color]

                    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.
                    [color=blue]
                    > On the other hand, I can't continue if the iterator's invalid, can I?[/color]

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

                    V
                    --
                    Please remove capital As from my address when replying by mail

                    Comment

                    • Victor Bazarov

                      #11
                      Re: How to delete stl&lt;map&gt; element from iterator?

                      Steve Edwards wrote:[color=blue]
                      > In article <0mIKf.2502$VI6 .433@newsread1. news.pas.earthl ink.net>,
                      > "Mike Wahler" <mkwahler@mkwah ler.net> wrote:[color=green]
                      >>"Steve Edwards" <gfx@lineone.ne t> wrote in message
                      >>news:gfx-D6FC33.17325521 022006@news.bti nternet.com...
                      >> [..][color=darkred]
                      >>>How do I actually delete the element that iter is pointing to?[/color]
                      >>
                      >>for(iter = m->begin(); iter != m->end(); ++iter)
                      >>{
                      >> if(condition)
                      >> iter = m->erase(iter);
                      >>}
                      >> [..][/color]
                      >
                      > My compiler is complaining about "iter = m->erase(iter); "[/color]

                      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
                      --
                      Please remove capital As from my address when replying by mail

                      Comment

                      • Mike Wahler

                        #12
                        Re: How to delete stl&lt;map&gt; element from iterator?


                        "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message
                        news:VJIKf.1336 $a97.597@newsre ad1.mlpsca01.us .to.verio.net.. .[color=blue]
                        > Mike Wahler wrote:[color=green]
                        >> "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message
                        >> news:mrIKf.1333 $a97.1001@newsr ead1.mlpsca01.u s.to.verio.net. ..
                        >>[color=darkred]
                        >>>Steve Edwards wrote:[/color]
                        >>
                        >>[color=darkred]
                        >>>>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:[/color]
                        >>
                        >>
                        >> Well, I think we both botched our replies. I forgot the
                        >> 'else' part, and yours disregards the invalid iterator. :-)[/color]
                        >
                        > Think again.[/color]

                        OK I did. I see I wasn't thinking before. :-)
                        [color=blue]
                        >[color=green]
                        >>
                        >>[color=darkred]
                        >>> for (.... ; ) // no increment at the end
                        >>> {
                        >>> a =
                        >>> b =
                        >>> if (..
                        >>> m->erase(iter++ );[/color]
                        >>
                        >>
                        >> iter = m->erase(iter);[/color][/color]

                        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


                        Comment

                        Working...