Erasing map elements by iterator

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Owen Brydon

    Erasing map elements by iterator

    Hi,

    Is the following code legal? g++ 3.2 barfs on it, although it seems
    fine to me.

    #include <map>

    using std::map;

    int main()
    {
    map<int,int> i;
    i[0]=6;
    i[54]=2;
    map<int,int>::i terator it=i.begin();
    while(it!=i.end ())
    {
    if(it->first==0) it=i.erase(it);
    else it++;
    }
    return 0;

    }

    The error message from g++ is:
    tmp.cpp:13: no match for `std::_Rb_tree_ iterator<std::p air<const int,
    int>,
    std::pair<const int, int>&, std::pair<const int, int>*>& = void'
    operator
    /usr/include/c++/3.2/bits/stl_tree.h:184: candidates are:
    std::_Rb_tree_i terator<std::pa ir<const int, int>, std::pair<const
    int,
    int>&, std::pair<const int, int>*>&
    std::_Rb_tree_i terator<std::pa ir<const
    int, int>, std::pair<const int, int>&, std::pair<const int,
    int>*>::operato r=(const std::_Rb_tree_i terator<std::pa ir<const int,
    int>,
    std::pair<const int, int>&, std::pair<const int, int>*>&)


    As a workaround, is it valid to do the following, or does erasing the
    iterator 'tmp' from the map (below) render the iterator 'it' invalid?
    #include <map>

    using std::map;

    int main()
    {
    map<int,int> i;
    i[0]=6;
    i[54]=2;
    map<int,int>::i terator it=i.begin();
    while(it!=i.end ())
    {
    if(it->first==0)
    {
    map<int,int>::i terator tmp=it;
    it++;
    i.erase(tmp);
    }
    else it++;
    }
    return 0;

    }

    Regards,

    Owen Brydon
  • Ron Natalie

    #2
    Re: Erasing map elements by iterator


    "Owen Brydon" <owen.brydon@st .com> wrote in message news:63a5125d.0 310150801.72168 52a@posting.goo gle.com...
    [color=blue]
    > Is the following code legal? g++ 3.2 barfs on it, although it seems
    > fine to me.[/color]

    It's not.
    [color=blue]
    > if(it->first==0) it=i.erase(it);[/color]

    map::erase returns void.

    if(it->first == 0) it.erase(it++);
    else ++it;



    Comment

    • Gianni Mariani

      #3
      Re: Erasing map elements by iterator

      Owen Brydon wrote:[color=blue]
      > Hi,
      >
      > Is the following code legal? g++ 3.2 barfs on it, although it seems
      > fine to me.
      >
      > #include <map>
      >
      > using std::map;
      >
      > int main()
      > {
      > map<int,int> i;
      > i[0]=6;
      > i[54]=2;
      > map<int,int>::i terator it=i.begin();
      > while(it!=i.end ())
      > {
      > if(it->first==0) it=i.erase(it);[/color]
      map::erase returns void
      [color=blue]
      > else it++;
      > }
      > return 0;
      >
      > }
      >
      > The error message from g++ is:
      > tmp.cpp:13: no match for `std::_Rb_tree_ iterator<std::p air<const int,
      > int>,
      > std::pair<const int, int>&, std::pair<const int, int>*>& = void'
      > operator[/color]

      gcc complains it can't find a void assignment ....
      [color=blue]
      >
      > As a workaround, is it valid to do the following, or does erasing the
      > iterator 'tmp' from the map (below) render the iterator 'it' invalid?[/color]

      The code is fine and likely the only way to do it. A map iterator
      remains valid for the life of the map entry.

      Comment

      • Owen Brydon

        #4
        Re: Erasing map elements by iterator

        Ron Natalie wrote:[color=blue]
        > "Owen Brydon" <owen.brydon@st .com> wrote in message
        > news:63a5125d.0 310150801.72168 52a@posting.goo gle.com...
        >
        >[color=green]
        >> Is the following code legal? g++ 3.2 barfs on it, although it seems
        >> fine to me.[/color]
        >
        >
        > It's not.
        >[color=green]
        >> if(it->first==0) it=i.erase(it);[/color]
        >[/color]
        It seems not :)
        In this case,
        http://www.dinkumware.com/manuals/re...=p/&h=map.html is
        incorrect, which is where I got the notion that it returned an iterator.

        [color=blue]
        > map::erase returns void.
        >
        > if(it->first == 0) it.erase(it++); else ++it;
        >[/color]

        Is this 100% safe? Is the iterator it valid for postincrement after
        being erased from the map?

        Is the other example I gave where the iterator is copied, then
        incremented, then the copy is erased, 100% safe?

        Regards,

        Owen Brydon

        Comment

        • grejdanospam@pacbell.net

          #5
          Re: Erasing map elements by iterator

          On Wed, 15 Oct 2003 18:52:30 +0100, Owen Brydon <owen@dsl.pipex .com> wrote:
          [color=blue]
          > Ron Natalie wrote:[color=green]
          >> "Owen Brydon" <owen.brydon@st .com> wrote in message
          >> news:63a5125d.0 310150801.72168 52a@posting.goo gle.com...
          >>
          >>[color=darkred]
          >>> Is the following code legal? g++ 3.2 barfs on it, although it seems
          >>> fine to me.[/color]
          >>
          >>
          >> It's not.
          >>[color=darkred]
          >>> if(it->first==0) it=i.erase(it);[/color]
          >>[/color]
          > It seems not :)
          > In this case,
          > http://www.dinkumware.com/manuals/re...=p/&h=map.html is
          > incorrect, which is where I got the notion that it returned an iterator.[/color]

          map erase(const key_type&) returns size_type
          [color=blue]
          >
          >[color=green]
          >> map::erase returns void.
          >>
          >> if(it->first == 0) it.erase(it++); else ++it;
          >>[/color]
          >
          > Is this 100% safe? Is the iterator it valid for postincrement after being
          > erased from the map?[/color]

          erase has an iterator argument, postincrement operator ++ applied to map
          iterator returns copy of current iterator and increments current iterator.
          [color=blue]
          >
          > Is the other example I gave where the iterator is copied, then
          > incremented, then the copy is erased, 100% safe?[/color]

          Yes,it is, as well as the shorter version above which does the same.
          [color=blue]
          >
          > Regards,
          >
          > Owen Brydon
          >
          >[/color]



          --
          grzegorz

          Comment

          • Andrew Koenig

            #6
            Re: Erasing map elements by iterator

            >> map::erase returns void.[color=blue][color=green]
            >> if(it->first == 0) it.erase(it++); else ++it;[/color][/color]

            Owen> Is this 100% safe? Is the iterator it valid for postincrement after
            Owen> being erased from the map?

            The example has a typographical error: it.erase(it++) should be
            i.erase(it++). With that change, the example is 100% safe:
            Although it skates right up to the edge of the broken ice, it
            avoids drowning in the frigid water.

            The key is that there is a sequence point between evaluating a
            function's arguments and calling the function, which means that
            before i.erase is called, the value of it has already been
            incremented. Therefore, it is no longer referring to the element
            that is about to be deleted, and its value therefore remains valid.

            --
            Andrew Koenig, ark@acm.org

            Comment

            Working...