-
May 7th, 2015, 01:48 AM
#1
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
-
May 7th, 2015, 02:03 AM
#2
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.
-
May 7th, 2015, 04:10 AM
#3
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
-
May 7th, 2015, 10:02 AM
#4
Re: How to make a std::map return null when there is nothing "at" a certain position?
Originally Posted by lucky6969b
...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...
-
May 7th, 2015, 10:24 AM
#5
Re: How to make a std::map return null when there is nothing "at" a certain position?
Originally Posted by VladimirF
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)
-
May 7th, 2015, 10:33 AM
#6
Re: How to make a std::map return null when there is nothing "at" a certain position?
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.
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).
-
May 7th, 2015, 11:06 AM
#7
Re: How to make a std::map return null when there is nothing "at" a certain position?
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.
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...
-
May 7th, 2015, 11:26 AM
#8
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.
-
May 7th, 2015, 11:34 AM
#9
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)
-
May 8th, 2015, 06:47 AM
#10
Re: How to make a std::map return null when there is nothing "at" a certain position?
Originally Posted by monarch_dodra
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.
-
May 8th, 2015, 08:26 AM
#11
Re: How to make a std::map return null when there is nothing "at" a certain position?
Originally Posted by OReubens
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.
-
May 8th, 2015, 09:41 AM
#12
Re: How to make a std::map return null when there is nothing "at" a certain position?
Originally Posted by OReubens
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;
Originally Posted by OReubens
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 ...
-
May 9th, 2015, 03:25 AM
#13
Re: How to make a std::map return null when there is nothing "at" a certain position?
Originally Posted by lucky6969b
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.
-
May 9th, 2015, 11:44 AM
#14
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);
// ...
-
May 9th, 2015, 11:16 PM
#15
Re: How to make a std::map return null when there is nothing "at" a certain position?
Originally Posted by superbonzo
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.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|