std::map

Discussion in 'C++' started by Duane Hebert, Sep 5, 2003.

  1. Duane Hebert

    Duane Hebert Guest

    2 questions:

    Given a map defined as

    std::map<int,string> stringmap;

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

    std::string spoo("doh");

    stringmap.insert(std::make_pair(1,spoo));


    // I tried this:
    for(std::map<int,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.find(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::getstring(size_t index) const { return
    stringmap[index];}

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

    const std::string classname::getstring(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.
    Duane Hebert, Sep 5, 2003
    #1
    1. Advertising

  2. Duane Hebert wrote in news:YY_5b.3557$:

    > 2 questions:
    >
    > Given a map defined as
    >
    > std::map<int,string> stringmap;
    >
    > //How do you access the data_type (string) via an iterator?
    >
    > std::string spoo("doh");
    >
    > stringmap.insert(std::make_pair(1,spoo));
    >
    >
    > // I tried this:
    > for(std::map<int,string> ::iterator it = stringmap.begin(); it !=
    > stringmap.end(); ++it)
    > std::cout << *it;


    Change this to it->second; if you want the key do it->first.

    >
    >
    > 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.find(1) != stringmap.end()) std::cout <<
    > stringmap[1];
    >
    >


    This should work fine stringmap should return a std::string &

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


    I don't really understand this, maybe you should post a complete
    example that doesen't compile.

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


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


    > but this compiles fine and seems to work with no problems:
    >
    > const std::string classname::getstring(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.


    Yes this is correct std::map<>::eek:perator[] 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::getstring( int index ) const
    {
    std::map<int,string>::iterator ptr =
    stringmap.find( index )
    :

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

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

    // the choice is your's.
    }


    HTH

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Sep 5, 2003
    #2
    1. Advertising

  3. Duane Hebert wrote:

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


    std::cout << it->second;

    should do the trick.

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


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


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

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


    > 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::getstring(size_t index) const { return
    > stringmap[index];}
    >
    > but this compiles fine and seems to work with no problems:
    >
    > const std::string classname::getstring(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.


    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
    Christoph Rabel, Sep 5, 2003
    #3
  4. Duane Hebert

    Smeckler Guest

    > > const std::string classname::getstring(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.

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


    But why doesn't map define a const operator[] in addition to the non const
    one?
    Smeckler, Sep 5, 2003
    #4
  5. Duane Hebert

    Smeckler Guest

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

    > What would it do if the key was not present in the map?
    >


    Errrr...do nothing and return a reference to NULL :)
    Smeckler, Sep 5, 2003
    #5
  6. Duane Hebert

    jeffc Guest

    "Duane Hebert" <> wrote in message
    news:YY_5b.3557$...
    > 2 questions:
    >
    > Given a map defined as
    >
    > std::map<int,string> stringmap;
    >
    > //How do you access the data_type (string) via an iterator?
    >
    > std::string spoo("doh");
    >
    > stringmap.insert(std::make_pair(1,spoo));
    >
    >
    > // I tried this:
    > for(std::map<int,string> ::iterator it = stringmap.begin(); it !=
    > stringmap.end(); ++it)
    > std::cout << *it;


    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".
    jeffc, Sep 5, 2003
    #6
  7. Duane Hebert

    Chris Theis Guest

    "Smeckler" <> wrote in message
    news:bja74t$p95$1$...
    > > > But why doesn't map define a const operator[] in addition to the non

    > const
    > > > one?
    > > >

    > > What would it do if the key was not present in the map?
    > >

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

    And how do you return a _reference_ to NULL?

    Chris
    Chris Theis, Sep 5, 2003
    #7
  8. Duane Hebert

    Ron Natalie Guest

    "Chris Theis" <> wrote in message news:bjauhc$dmr$...
    >
    > "Smeckler" <> wrote in message
    > news:bja74t$p95$1$...
    > > > > But why doesn't map define a const operator[] in addition to the non

    > > const
    > > > > one?
    > > > >
    > > > What would it do if the key was not present in the map?
    > > >

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

    > And how do you return a _reference_ to NULL?
    >

    That was a joke, son. (Didn't you see the smilely?)
    Ron Natalie, Sep 5, 2003
    #8
  9. Duane Hebert

    Duane Hebert Guest

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

    >
    > Change this to it->second; if you want the key do it->first.


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


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

    >
    > This should work fine stringmap should return a std::string &


    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 :)


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

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



    > > but this compiles fine and seems to work with no problems:
    > >
    > > const std::string classname::getstring(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.

    >
    > Yes this is correct std::map<>::eek:perator[] 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::getstring( int index ) const
    > {
    > std::map<int,string>::iterator ptr =
    > stringmap.find( index )
    > :
    >
    > if ( ptr != stringmap.end() ) return ptr->second;


    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.

    > HTH


    It does. Thanks.
    Duane Hebert, Sep 6, 2003
    #9
  10. Duane Hebert wrote:
    >>std::string classname::getstring( int index ) const
    >>{
    >> std::map<int,string>::iterator ptr =
    >> stringmap.find( index )
    >> :
    >>
    >> if ( ptr != stringmap.end() ) return ptr->second;

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


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

    Christoph
    Christoph Rabel, Sep 6, 2003
    #10
  11. Duane Hebert wrote in news:Ii96b.10301$:

    > std::string classname::getstring( int index ) const
    >> {
    >> std::map<int,string>::iterator ptr =
    >> stringmap.find( index )
    >> :
    >>
    >> if ( ptr != stringmap.end() ) return ptr->second;

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


    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<>::find( Key ) const, which returns a const_iterator.

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Sep 6, 2003
    #11
  12. Duane Hebert

    Duane Hebert Guest

    > 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<>::find( Key ) const, which returns a const_iterator.


    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.
    Duane Hebert, Sep 6, 2003
    #12
  13. Duane Hebert

    Duane Hebert Guest

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

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


    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".
    Duane Hebert, Sep 7, 2003
    #13
  14. 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.
    >
    > 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.


    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.
    Kevin Goodsell, Sep 7, 2003
    #14
  15. Duane Hebert

    Smeckler Guest

    "Chris Theis" <> wrote in message
    news:bjauhc$dmr$...
    >
    > "Smeckler" <> wrote in message
    > news:bja74t$p95$1$...
    > > > > But why doesn't map define a const operator[] in addition to the non

    > > const
    > > > > one?
    > > > >
    > > > What would it do if the key was not present in the map?
    > > >

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

    > And how do you return a _reference_ to NULL?
    >
    > Chris


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

    template <typename TypeName> TypeName& GetNullReference()
    {
    return *(TypeName*)NULL;
    }
    Smeckler, Sep 8, 2003
    #15
  16. Duane Hebert

    jeffc Guest

    "Duane Hebert" <> wrote in message
    news:nsH6b.1873$...
    > >
    > > 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".

    >
    > Right but *it.second doesn't work.


    So?

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


    Yuck. Why would you want to muck it up like that? it->second is perfectly
    natural. I think it's crazy to say pointer notation "obscures" the fact
    that the dereferenced pointer is a reference. That's like saying you prefer
    the statement "It's false that I don't like pie" to the statement "I like
    pie." because the second sentence obscures the fact that you don't dislike
    it.
    jeffc, Sep 8, 2003
    #16
  17. Duane Hebert

    llewelly Guest

    "Smeckler" <> writes:
    [snip]
    > Easy. And, since this is the STL we're talking about, why not create a
    > handy template function :)
    >
    > template <typename TypeName> TypeName& GetNullReference()
    > {
    > return *(TypeName*)NULL;
    > }


    This has undefined behavior.
    llewelly, Sep 8, 2003
    #17
  18. Smeckler wrote:

    >
    > Easy. And, since this is the STL we're talking about, why not create a
    > handy template function :)
    >
    > template <typename TypeName> TypeName& GetNullReference()
    > {
    > return *(TypeName*)NULL;
    > }
    >
    >


    I hope you are joking. If not, you need to learn some C++.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Sep 8, 2003
    #18
  19. Duane Hebert

    Duane Hebert Guest

    > Yuck. Why would you want to muck it up like that? it->second is
    perfectly
    > natural. I think it's crazy to say pointer notation "obscures" the fact
    > that the dereferenced pointer is a reference. That's like saying you

    prefer
    > the statement "It's false that I don't like pie" to the statement "I like
    > pie." because the second sentence obscures the fact that you don't dislike
    > it.


    I prefer to use the dot operator when referencing an object that's not a
    pointer. It's
    a matter of taste and not worth an argument. Both ways work. To me, it
    wasn't intuitive
    that (*it).first would work. But to answer your simile, I guess that it's
    not true that I do
    agree with you :)
    Duane Hebert, Sep 9, 2003
    #19
  20. Duane Hebert

    Smeckler Guest

    > > Easy. And, since this is the STL we're talking about, why not create a
    > > handy template function :)
    > >
    > > template <typename TypeName> TypeName& GetNullReference()
    > > {
    > > return *(TypeName*)NULL;
    > > }
    > >
    > >

    >
    > I hope you are joking. If not, you need to learn some C++.
    >
    > -Kevin



    Kevin,

    Would you care to be more specific about your objection to my code?
    Smeckler, Sep 9, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matthias Hildebrand
    Replies:
    5
    Views:
    7,940
    krogers
    Mar 20, 2012
  2. Peter Jansson
    Replies:
    5
    Views:
    6,276
    Ivan Vecerina
    Mar 17, 2005
  3. Replies:
    1
    Views:
    409
    red floyd
    Dec 21, 2008
  4. Thomas J. Gritzan
    Replies:
    6
    Views:
    1,001
    James Kanze
    Dec 22, 2008
  5. James Kanze
    Replies:
    0
    Views:
    1,985
    James Kanze
    Dec 21, 2008
Loading...

Share This Page