return element in a map

This is a discussion on return element in a map within the C++ Programming forums, part of the General Programming Boards category; Hello Whats the right way to return reference to element in a map (in one line): Code: class someclass { ...

  1. #1
    l2u
    l2u is offline
    Registered User
    Join Date
    May 2006
    Posts
    630

    return element in a map

    Hello

    Whats the right way to return reference to element in a map (in one line):

    Code:
    class someclass {
    public:
      element &get_element(std::string key) { return *(m_map.find(key)); }
    
    private:
      std::map<std::string, element> m_map;
    };
    Thanks for help!

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,256
    That would be:
    Code:
    class someclass {
    public:
      element& get_element(const std::string& key) { return m_map[key]; }
    
    private:
      std::map<std::string, element> m_map;
    };
    Of course, if key does not exist then it would be added to the map. If you do not want this behaviour, then another option is:
    Code:
    class someclass {
    public:
      element& get_element(const std::string& key)
      {
      	std::map<std::string, element>:iterator iter = m_map.find(key);
      	if (iter == m_map.end())
      	{
          throw std::out_of_range("Invalid key: " + key);
      	}
      	return *iter;
      }
    private:
      std::map<std::string, element> m_map;
    };
    Yet another option is to stick to what you have now, but state that if someone attempts to use a key that does not exist, the behaviour is undefined.
    Last edited by laserlight; 04-22-2008 at 05:15 AM. Reason: Fixed typo error pointed out by matsp.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,344
    And yet another variation is:
    Code:
    class someclass {
    public:
      element &get_element(std::string key)
      {
        assert(m_map.find(key) != m_map.end());
        return m_map.find(key)->second;
      }
    
    private:
      std::map<std::string, element> m_map;
    };
    Last edited by Daved; 04-22-2008 at 07:35 AM. Reason: fix bug

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    In laserlight's post there is an ill-placed return keyword that needs to be removed to compile correctly:
    Code:
      	std::map<std::string, element>:iterator iter = return m_map.find(key);
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by Daved View Post
    And yet another variation is:
    Code:
    class someclass {
    public:
      element &get_element(std::string key)
      {
        assert(m_map.find(key) != m_map.end());
        return *(m_map.find(key));
      }
    
    private:
      std::map<std::string, element> m_map;
    };
    An exception is preferable here. Assertions should be fired for programmer errors, not usage errors. They are also compiled out of release builds, usually.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,344
    That is why the assert is an option. Based on previous threads from the OP, it is entirely likely that an invalid key is a programmer error and can only happen due to programming error. It is one step better than the "undefined behavior" solution by itself. The fact that the assert is compiled out of release builds is a positive, because that situation should never occur and so there should be no need to waste time checking the iterator against end().

  7. #7
    l2u
    l2u is offline
    Registered User
    Join Date
    May 2006
    Posts
    630
    Why will this produce the following error:

    Code:
    class someclass {
    public:
      element &get_element(std::string key) {
        assert(m_map.find(key) != m_map.end());
        return *(m_map.find(key));
      }
    
    private:
      std::map<std::string, element> m_map;
    };
    Code:
    error C2440: 'return' : cannot convert from 'std::pair<_Ty1,_Ty2>' to 'element &'
    Thanks again!

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,256
    Oh yes, we overlooked the fact that a map iterator is a pair consisting of the key and the value. Since you only want the value, you should return m_map.find(key)->second (or in my example, iter->second).
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by Daved View Post
    That is why the assert is an option. Based on previous threads from the OP, it is entirely likely that an invalid key is a programmer error and can only happen due to programming error.
    Well, OK, I guess I don't recall any related threads, but this sure looked like a situation where recovery was possible.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,344
    l2u's had threads about this over the last couple weeks you can search for if you're curious about the back story. It doesn't really matter for the point at hand though, since we're just discussing potential solutions rather than specifically identifying the "correct" one.

    I think the assert is a valid solution even if recovery is possible. Look at vector's operator[] and at() functions. Both present valid solutions to the problem. One uses undefined behavior (potentially with an assert or debug-only error of some kind). The other uses an exception. You use each in different circumstances depending on what you need.

    Personally, I would normally prefer a defined solution despite potential performance costs because I'd rather have the code work in all cases than prematurely optimize. However, the implementation cost of catching the out_of_range error in an appropriate place may be significant, and so leaving the behavior undefined might be more appropriate for a situation that should never happen.

  11. #11
    l2u
    l2u is offline
    Registered User
    Join Date
    May 2006
    Posts
    630
    With:

    Code:
    return *(m_map.find(key)->second);
    I get error:
    Code:
    error C2440: 'return' : cannot convert from 'std::string' to 'element &'

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    22,985
    Element is the key, and std::string is what you store. iterator->first pointers to the key, and iterator->second points to the actual stored value.
    You need to return std::string, because that's what you're storing in the map.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,256
    hmm... but the original post gives m_map as:
    Code:
    std::map<std::string, element> m_map;
    Clearly, std::string is the key type, element is the mapped type.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    22,985
    But somewhat that cannot be it if iterator->second is element.
    Anyway, the best way, I think, is just to post the code. This should clear any confusion.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    l2u
    l2u is offline
    Registered User
    Join Date
    May 2006
    Posts
    630
    Quote Originally Posted by laserlight View Post
    hmm... but the original post gives m_map as:
    Code:
    std::map<std::string, element> m_map;
    Clearly, std::string is the key type, element is the mapped type.
    I think I know what the problem is.. Class element has * operator overloaded and it returns a string (when I do *element).. So what the solution would be in that case so that I can leave the overloaded operator on the element class?

    Thanks!

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 02:01 AM
  2. Linking OpenGL in Dev-C++
    By linkofazeroth in forum Game Programming
    Replies: 4
    Last Post: 09-13-2005, 11:17 AM
  3. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 04:00 PM
  4. Certain functions
    By Lurker in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2003, 01:26 AM
  5. OpenGL and Windows
    By sean345 in forum Game Programming
    Replies: 5
    Last Post: 06-24-2002, 11:14 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21