std::map

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Duane Hebert

    std::map

    2 questions:

    Given a map defined as

    std::map<int,st ring> stringmap;

    //How do you access the data_type (string) via an iterator?

    std::string spoo("doh");

    stringmap.inser t(std::make_pai r(1,spoo));


    // I tried this:
    for(std::map<in t,string> ::iterator it = stringmap.begin (); it !=
    stringmap.end() ; ++it)
    std::cout << *it;


    But this doesn't compile with error that the operator+ has not been defined
    ....
    I think the problem is that the iterator returns a pair. Is it possible to
    do this?

    I know I can do:
    if(stringmap.fi nd(1) != stringmap.end() ) std::cout << stringmap[1];


    2nd question:

    This doesn't work with BCB6 (causes a compile error about casting a pair to
    an int???)

    //stringmap is defined as a private class member
    const std::string classname::gets tring(size_t index) const { return
    stringmap[index];}

    but this compiles fine and seems to work with no problems:

    const std::string classname::gets tring(size_t index) { return
    stringmap[index];}

    Is this correct? Why can I not define this function as const? It's not
    changing any
    member data.

    Thanks.





  • Christoph Rabel

    #2
    Re: std::map

    Duane Hebert wrote:
    [color=blue]
    > // I tried this:
    > for(std::map<in t,string> ::iterator it = stringmap.begin (); it !=
    > stringmap.end() ; ++it)
    > std::cout << *it;[/color]

    std::cout << it->second;

    should do the trick.

    Btw I recommend that you use a const_iterator instead of an
    iterator.

    [color=blue]
    > I know I can do:
    > if(stringmap.fi nd(1) != stringmap.end() ) std::cout << stringmap[1];[/color]

    Brr, this is terribly inefficient. Why dont you store the
    returnvalue of find?

    if((it = stringmap.find( 1)) != stringmap.end() )
    std::cout << it->second;

    [color=blue]
    > 2nd question:
    >
    > This doesn't work with BCB6 (causes a compile error about casting a pair to
    > an int???)
    >
    > //stringmap is defined as a private class member
    > const std::string classname::gets tring(size_t index) const { return
    > stringmap[index];}
    >
    > but this compiles fine and seems to work with no problems:
    >
    > const std::string classname::gets tring(size_t index) { return
    > stringmap[index];}
    >
    > Is this correct? Why can I not define this function as const? It's not
    > changing any member data.[/color]

    Because operator[] is not const. It might change the
    contents of your stringmap. The map is const in this
    function, so you are not allowed to call it.

    Use find instead.

    hope this helps,

    Christoph

    Comment

    • Rob Williscroft

      #3
      Re: std::map

      Duane Hebert wrote in news:YY_5b.3557 $za.250775@wagn er.videotron.ne t:
      [color=blue]
      > 2 questions:
      >
      > Given a map defined as
      >
      > std::map<int,st ring> stringmap;
      >
      > //How do you access the data_type (string) via an iterator?
      >
      > std::string spoo("doh");
      >
      > stringmap.inser t(std::make_pai r(1,spoo));
      >
      >
      > // I tried this:
      > for(std::map<in t,string> ::iterator it = stringmap.begin (); it !=
      > stringmap.end() ; ++it)
      > std::cout << *it;[/color]

      Change this to it->second; if you want the key do it->first.
      [color=blue]
      >
      >
      > But this doesn't compile with error that the operator+ has not been
      > defined ...
      > I think the problem is that the iterator returns a pair. Is it
      > possible to do this?
      >
      > I know I can do:
      > if(stringmap.fi nd(1) != stringmap.end() ) std::cout <<
      > stringmap[1];
      >
      >[/color]

      This should work fine stringmap[i] should return a std::string &
      [color=blue]
      > 2nd question:
      >
      > This doesn't work with BCB6 (causes a compile error about casting a
      > pair to an int???)[/color]

      I don't really understand this, maybe you should post a complete
      example that doesen't compile.
      [color=blue]
      >
      > //stringmap is defined as a private class member
      > const std::string classname::gets tring(size_t index) const { return
      > stringmap[index];}
      >[/color]

      A return of std::string const & would be more effecient here.

      [color=blue]
      > but this compiles fine and seems to work with no problems:
      >
      > const std::string classname::gets tring(size_t index) { return
      > stringmap[index];}
      >
      > Is this correct? Why can I not define this function as const? It's
      > not changing any
      > member data.[/color]

      Yes this is correct std::map<>::ope rator[] is not defined as a
      const-member function, this is because the non-const version
      will insert a new element into the map if it doesn't exist.

      std::string classname::gets tring( int index ) const
      {
      std::map<int,st ring>::iterator ptr =
      stringmap.find( index )
      :

      if ( ptr != stringmap.end() ) return ptr->second;

      // return std::string( "< some default>" );
      //throw std::runtime_er ror( "Item Not Found" );

      // the choice is your's.
      }


      HTH

      Rob.
      --

      Comment

      • Smeckler

        #4
        Re: std::map

        > > const std::string classname::gets tring(size_t index) { return[color=blue][color=green]
        > > stringmap[index];}
        > >
        > > Is this correct? Why can I not define this function as const? It's not
        > > changing any member data.[/color]
        >
        > Because operator[] is not const. It might change the
        > contents of your stringmap. The map is const in this
        > function, so you are not allowed to call it.[/color]

        But why doesn't map define a const operator[] in addition to the non const
        one?


        Comment

        • Smeckler

          #5
          Re: std::map

          > > But why doesn't map define a const operator[] in addition to the non
          const[color=blue][color=green]
          > > one?
          > >[/color]
          > What would it do if the key was not present in the map?
          >[/color]

          Errrr...do nothing and return a reference to NULL :)


          Comment

          • jeffc

            #6
            Re: std::map


            "Duane Hebert" <spoo@flarn.com > wrote in message
            news:YY_5b.3557 $za.250775@wagn er.videotron.ne t...[color=blue]
            > 2 questions:
            >
            > Given a map defined as
            >
            > std::map<int,st ring> stringmap;
            >
            > //How do you access the data_type (string) via an iterator?
            >
            > std::string spoo("doh");
            >
            > stringmap.inser t(std::make_pai r(1,spoo));
            >
            >
            > // I tried this:
            > for(std::map<in t,string> ::iterator it = stringmap.begin (); it !=
            > stringmap.end() ; ++it)
            > std::cout << *it;[/color]

            So you've figured out that you need to insert pairs, so the thing in the map
            that the iterator is pointing to is a pair. You also said you want only the
            string, not the whole pair. *it would be the whole pair. In a pair, there
            is a "first" and "second". You want to point to the "second".


            Comment

            • Chris Theis

              #7
              Re: std::map


              "Smeckler" <smNOecklers@ho tSPAMmail.com> wrote in message
              news:bja74t$p95 $1$8302bc10@new s.demon.co.uk.. .[color=blue][color=green][color=darkred]
              > > > But why doesn't map define a const operator[] in addition to the non[/color][/color]
              > const[color=green][color=darkred]
              > > > one?
              > > >[/color]
              > > What would it do if the key was not present in the map?
              > >[/color]
              >
              > Errrr...do nothing and return a reference to NULL :)
              >[/color]
              And how do you return a _reference_ to NULL?

              Chris


              Comment

              • Ron Natalie

                #8
                Re: std::map


                "Chris Theis" <Christian.Thei s@nospam.cern.c h> wrote in message news:bjauhc$dmr $1@sunnews.cern .ch...[color=blue]
                >
                > "Smeckler" <smNOecklers@ho tSPAMmail.com> wrote in message
                > news:bja74t$p95 $1$8302bc10@new s.demon.co.uk.. .[color=green][color=darkred]
                > > > > But why doesn't map define a const operator[] in addition to the non[/color]
                > > const[color=darkred]
                > > > > one?
                > > > >
                > > > What would it do if the key was not present in the map?
                > > >[/color]
                > >
                > > Errrr...do nothing and return a reference to NULL :)
                > >[/color]
                > And how do you return a _reference_ to NULL?
                >[/color]
                That was a joke, son. (Didn't you see the smilely?)


                Comment

                • Duane Hebert

                  #9
                  Re: std::map

                  > > // I tried this:[color=blue][color=green]
                  > > for(std::map<in t,string> ::iterator it = stringmap.begin (); it !=
                  > > stringmap.end() ; ++it)
                  > > std::cout << *it;[/color]
                  >
                  > Change this to it->second; if you want the key do it->first.[/color]

                  Thanks. I stumbled on that myself. I also found that
                  std::cout (*it).second; works as well. This was what I tried
                  originally but I missed the () .

                  [color=blue][color=green]
                  > > I know I can do:
                  > > if(stringmap.fi nd(1) != stringmap.end() ) std::cout <<
                  > > stringmap[1];
                  > >
                  > >[/color]
                  >
                  > This should work fine stringmap[i] should return a std::string &[/color]

                  That's correct but if I want to access each element of the map with a for
                  loop
                  it requires that I know the min and max keys and try all of them. That's
                  why
                  I wanted to get the iterator to work. (also to figure it out :-)

                  [color=blue][color=green]
                  > > //stringmap is defined as a private class member
                  > > const std::string classname::gets tring(size_t index) const { return
                  > > stringmap[index];}
                  > >[/color]
                  >
                  > A return of std::string const & would be more effecient here.[/color]

                  [color=blue][color=green]
                  > > but this compiles fine and seems to work with no problems:
                  > >
                  > > const std::string classname::gets tring(size_t index) { return
                  > > stringmap[index];}
                  > >
                  > > Is this correct? Why can I not define this function as const? It's
                  > > not changing any
                  > > member data.[/color]
                  >
                  > Yes this is correct std::map<>::ope rator[] is not defined as a
                  > const-member function, this is because the non-const version
                  > will insert a new element into the map if it doesn't exist.
                  >
                  > std::string classname::gets tring( int index ) const
                  > {
                  > std::map<int,st ring>::iterator ptr =
                  > stringmap.find( index )
                  > :
                  >
                  > if ( ptr != stringmap.end() ) return ptr->second;[/color]

                  This didn't exactly work on my compiler. Threw the same error as before.
                  I had to make ptr a const_iterator,
                  then it worked fine. Not sure why since find() returns an iterator,
                  but thanks for the help.
                  [color=blue]
                  > HTH[/color]

                  It does. Thanks.


                  Comment

                  • Christoph Rabel

                    #10
                    Re: std::map

                    Duane Hebert wrote:[color=blue][color=green]
                    >>std::string classname::gets tring( int index ) const
                    >>{
                    >> std::map<int,st ring>::iterator ptr =
                    >> stringmap.find( index )
                    >> :
                    >>
                    >> if ( ptr != stringmap.end() ) return ptr->second;[/color]
                    >
                    > This didn't exactly work on my compiler. Threw the same error as before.
                    > I had to make ptr a const_iterator,
                    > then it worked fine. Not sure why since find() returns an iterator,
                    > but thanks for the help.[/color]

                    No, because the stringmap is const in this function find
                    returns a const_iterator in this case.

                    Christoph

                    Comment

                    • Rob Williscroft

                      #11
                      Re: std::map

                      Duane Hebert wrote in news:Ii96b.1030 1$za.434818@wag ner.videotron.n et:
                      [color=blue]
                      > std::string classname::gets tring( int index ) const[color=green]
                      >> {
                      >> std::map<int,st ring>::iterator ptr =
                      >> stringmap.find( index )
                      >> :
                      >>
                      >> if ( ptr != stringmap.end() ) return ptr->second;[/color]
                      >
                      > This didn't exactly work on my compiler. Threw the same error as
                      > before. I had to make ptr a const_iterator,
                      > then it worked fine. Not sure why since find() returns an iterator,
                      > but thanks for the help.
                      >
                      >[/color]

                      My code was wrong, but fortunatly your compiler cought the error.

                      Since this is a const member function the member stingmap is
                      effectivly constant within it so stringmap.find( index ) is calling
                      std::map<>::fin d( Key ) const, which returns a const_iterator.

                      Rob.
                      --

                      Comment

                      • Duane Hebert

                        #12
                        Re: std::map

                        > My code was wrong, but fortunatly your compiler cought the error.[color=blue]
                        >
                        > Since this is a const member function the member stingmap is
                        > effectivly constant within it so stringmap.find( index ) is calling
                        > std::map<>::fin d( Key ) const, which returns a const_iterator.[/color]

                        Borland 's BCB6 uses StlPort which seems to be pretty compliant and
                        less buggy than the RogueWave implementations of previous editions.
                        The help for the stl containers is not the best though. I'll be getting a
                        couple of books soon.


                        Comment

                        • Duane Hebert

                          #13
                          Re: std::map

                          > > // I tried this:[color=blue][color=green]
                          > > for(std::map<in t,string> ::iterator it = stringmap.begin (); it !=
                          > > stringmap.end() ; ++it)
                          > > std::cout << *it;[/color]
                          >
                          > So you've figured out that you need to insert pairs, so the thing in the[/color]
                          map[color=blue]
                          > that the iterator is pointing to is a pair. You also said you want only[/color]
                          the[color=blue]
                          > string, not the whole pair. *it would be the whole pair. In a pair,[/color]
                          there[color=blue]
                          > is a "first" and "second". You want to point to the "second".[/color]

                          Right but *it.second doesn't work. (second is not a member of iterator)
                          This was my problem. I could create a
                          pair from *it and it would work. I didn't realize that there are two
                          operators
                          in the line *it.second, the . and the * and the . has precedence. So this
                          line
                          turns into *(it.second).
                          One solution would be to do it->first since it returns a reference.
                          I don't like this because I think that it obscures the fact that *it is a
                          reference.
                          The solution that I was looking for was simply (*it).second.

                          The answers that I received here were very helpful. std::map is different
                          from containers
                          like vectors and sets in that it contains another "container" .


                          Comment

                          • Kevin Goodsell

                            #14
                            Re: std::map

                            Duane Hebert wrote:

                            Duane, look at the formatting of your messages. Are you hitting <enter>
                            at the end of your lines or something? Please don't do that. Set your
                            news client's line wrap to a reasonable length (around 72 is good) and
                            let it do the wrapping.[color=blue]
                            >
                            > Right but *it.second doesn't work. (second is not a member of iterator)
                            > This was my problem. I could create a
                            > pair from *it and it would work. I didn't realize that there are two
                            > operators
                            > in the line *it.second, the . and the * and the . has precedence. So this
                            > line
                            > turns into *(it.second).
                            > One solution would be to do it->first since it returns a reference.
                            > I don't like this because I think that it obscures the fact that *it is a
                            > reference.[/color]

                            It absolutely does not. Every C & C++ programmer recognizes immediately
                            that a->b means (*a).b. If anything the 'arrow' syntax is less confusing.

                            -Kevin
                            --
                            My email address is valid, but changes periodically.
                            To contact me please use the address from a recent posting.

                            Comment

                            • Smeckler

                              #15
                              Re: std::map

                              "Chris Theis" <Christian.Thei s@nospam.cern.c h> wrote in message
                              news:bjauhc$dmr $1@sunnews.cern .ch...[color=blue]
                              >
                              > "Smeckler" <smNOecklers@ho tSPAMmail.com> wrote in message
                              > news:bja74t$p95 $1$8302bc10@new s.demon.co.uk.. .[color=green][color=darkred]
                              > > > > But why doesn't map define a const operator[] in addition to the non[/color]
                              > > const[color=darkred]
                              > > > > one?
                              > > > >
                              > > > What would it do if the key was not present in the map?
                              > > >[/color]
                              > >
                              > > Errrr...do nothing and return a reference to NULL :)
                              > >[/color]
                              > And how do you return a _reference_ to NULL?
                              >
                              > Chris[/color]

                              Easy. And, since this is the STL we're talking about, why not create a
                              handy template function :)

                              template <typename TypeName> TypeName& GetNullReferenc e()
                              {
                              return *(TypeName*)NUL L;
                              }


                              Comment

                              Working...