CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Join Date
    Dec 2010
    Posts
    907

    How to make a std::map return null when there is nothing "at" a certain position?

    Code:
    std::map<int, DWORD> unitColors;
    DWORD color = unitColors.at(unit->id);
    I want to use a color value of 0x00000000 when
    a DWORD at unit->id of unitColors is unavailable.
    Is it possible?
    Thanks
    Jack

  2. #2
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Make use of the find member function instead of operator[]. This way, when find returns an iterator equal to unitColors.end(), you know that you should use your default value instead.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  3. #3
    Join Date
    Dec 2010
    Posts
    907

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Thanks, I think about it that way, just wondering if there are any alternatives.
    So you've confirmed me about this.
    Thanks a lot
    Jack

  4. #4
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by lucky6969b View Post
    ...just wondering if there are any alternatives.
    Code:
    std::map<int, DWORD> unitColors;
    DWORD color = unitColors[42];
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,825

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by VladimirF View Post
    Code:
    std::map<int, DWORD> unitColors;
    DWORD color = unitColors[42];
    but that will also insert a new element of key 42 into the map if one does not already exist which may not be what the OP requires. The code in post #1 uses .at() which doesn't insert if the required key is not found.

    Using the .at(), color can be set to 0x0 in the catch part of a try/catch.

    Code:
    DWORD color;
    try
    {
         color = unitColors.at(unit->id);
    }
    catch (const out_of_range& oor)
    {
         color = 0;
    }
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by 2kaud
    but that will also insert a new element of key 42 into the map if one does not already exist which may not be what the OP requires.
    Yeah, that's why I suggested using find instead of operator[]. On closer inspection though, lucky6969b's default value is 0, and since value initialisation of an integer type would result in zero initialisation, VladimirF's suggestion will work as long as lucky6969b's default value is zero.

    Quote Originally Posted by 2kaud
    Using the .at(), color can be set to 0x0 in the catch part of a try/catch.
    True, but if the key being missing is expected under the normal usage, I think that this is not good C++-style. (Even in Python, where it is better to ask for forgiveness than for permission is held to be good style, programmers may still prefer to check instead of catch the exception if the exception is expected to be thrown more often than not).
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  7. #7
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by 2kaud View Post
    but that will also insert a new element of key 42 into the map if one does not already exist which may not be what the OP requires.
    This, of course, is true. But we don't know what OP requirements are.
    Also, my suggestion will ONLY work (as laserlight noted) if the value 0 works for missing keys. Luckily, that's what lucky wanted
    Please note that I strictly answered OP's Q: "...just wondering if there are any alternatives" - there are!
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  8. #8
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    I'd go for either:

    Code:
    auto it = unitColors.find(unit->id);
    auto color = it != unitColors.end() : *it ? DWord{0};
    Code:
    auto color = DWORD{0};
    if (unitColors.find(unit->id) != unitColors.end())
    {
         color = unitColors[unit->id];
    }
    Code:
    color = DWORD{0};
    auto it = unitColors.find(unit->id);
    if (it != unitColors.end())
    {
         color = *it;
    }
    Depending on my mood and/or context where the code is encountered.

    Eitherway, I'd use some favor of find. And I most certainly would NOT use at if I plan to handle it.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  9. #9
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,825

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    And I most certainly would NOT use at if I plan to handle it.
    True, but as Vladimir pointed out, the OP asked if there were any alternatives...
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #10
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by monarch_dodra View Post
    And I most certainly would NOT use at if I plan to handle it.
    Well maybe you would.
    Consider a bunch of code where you have a LOT of lookups into a map and a failure of any can be handled in a single catch.
    In that case, a try/catch would be preferable to littering the rest of the code with lots of tests if the lookup succeeded.

    This is the big bonus about try/catch afterall. Not that you can catch a single exception, but that you can catch ALL the exceptions in a block of code.

    Code:
    int find_my_thinghy(int x)
    {
       int ret(0);
       try
       {
          if (color.at(x) + color.at(x*2) + color.at(x*3) + color.at(x*4) <= color.at(105+x*(x-1)) * color.at(x/5))
          {
               ret = color.at(x+1) + color.at((x+1)*2);
          }
          else
          {
              ret = color.at(x-1) * color.at(x/6);
          }  
       }
       catch (const out_of_range& oor)
       {
          ret=-1; // though it might be a good idea to throw something else instead
       }
       return ret;
    }
    Challenge: write the equivalent code using proper error handling with find() and see if you like it. ;-)
    Last edited by OReubens; May 8th, 2015 at 06:50 AM.

  11. #11
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by OReubens View Post
    Well maybe you would.
    Consider a bunch of code where you have a LOT of lookups into a map and a failure of any can be handled in a single catch.
    In that case, a try/catch would be preferable to littering the rest of the code with lots of tests if the lookup succeeded.

    This is the big bonus about try/catch afterall. Not that you can catch a single exception, but that you can catch ALL the exceptions in a block of code.

    Code:
    int find_my_thinghy(int x)
    {
       int ret(0);
       try
       {
          if (color.at(x) + color.at(x*2) + color.at(x*3) + color.at(x*4) <= color.at(105+x*(x-1)) * color.at(x/5))
          {
               ret = color.at(x+1) + color.at((x+1)*2);
          }
          else
          {
              ret = color.at(x-1) * color.at(x/6);
          }  
       }
       catch (const out_of_range& oor)
       {
          ret=-1; // though it might be a good idea to throw something else instead
       }
       return ret;
    }
    Challenge: write the equivalent code using proper error handling with find() and see if you like it. ;-)
    Fine: "And I most certainly would NOT use at if I plan to IMMEDIATELY handle it." (https://isocpp.org/wiki/faq/exceptio...rycatch-blocks)
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  12. #12
    Join Date
    Oct 2008
    Posts
    1,456

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by OReubens View Post
    Well maybe you would.
    Consider a bunch of code where you have a LOT of lookups into a map and a failure of any can be handled in a single catch.
    In that case, a try/catch would be preferable to littering the rest of the code with lots of tests if the lookup succeeded.
    but this is not what the OP asked for; he's not trying to handle errors, he wants a "find" with a zero fallback value;

    Quote Originally Posted by OReubens View Post
    Challenge: write the equivalent code using proper error handling with find() and see if you like it. ;-)
    is the -1 return value an error code or a valid result ? in the latter case, I'd say that a find() based solution, albeit much more verbose, could actually turn out easier to ( fully ) understand ... using exceptions for anything other than exceptional errors is morally wrong ...

  13. #13
    Join Date
    Jul 2013
    Posts
    576

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by lucky6969b View Post
    Is it possible?
    Certainly (as all replies show) but regardless of how you decide to do it I suggest you encapsulate the map, the initialization of the map and accesses to the map in a class called say UnitColors sporting a method called say idToColor().

    Everything regarding UnitColors is now in one place. Implementation details are hidden and can be changed independently. Usage is simply,

    Code:
    UnitColors unitColors;
    //
    DWORD color = unitColors.idToColor(unit->id);
    Since style has been mentioned I think abstractions like this (hiding the messy details) are key to good C++.
    Last edited by razzle; May 9th, 2015 at 04:40 AM.

  14. #14
    Join Date
    Oct 2008
    Posts
    1,456

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    and if you need this only in one place, so that creating a new class just for that it's not worth it, but using find() makes your code difficult to follow, it's easy to write a local lambda nowadays:

    Code:
    auto unitColors_at_or_zero = [&]( auto id ){ auto it = unitColors.find(id); return it != unitColors.end() ? *it : 0; };
    
    DWORD color1 = unitColors_at_or_zero(unit->id);
    // ...

  15. #15
    Join Date
    Jul 2013
    Posts
    576

    Re: How to make a std::map return null when there is nothing "at" a certain position?

    Quote Originally Posted by superbonzo View Post
    and if you need this only in one place, so that creating a new class just for that it's not worth it, but using find() makes your code difficult to follow, it's easy to write a local lambda nowadays:

    Code:
    auto unitColors_at_or_zero = [&]( auto id ){ auto it = unitColors.find(id); return it != unitColors.end() ? *it : 0; };
    
    DWORD color1 = unitColors_at_or_zero(unit->id);
    // ...
    That's typical feature overuse. Something a pumped up newbie would put in to show off. You get the worst of two worlds:

    As implementation it's too much. What's wrong with a simple free function?

    As abstraction it's too little. What's wrong with a class? Proper encapsulation is always worthwhile also in a limited scope.
    Last edited by razzle; May 10th, 2015 at 01:36 AM.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured