12 Jan, 2007, Guest wrote in the 1st comment:
Votes: 0
CMDF( do_maptest )
{
map<int,int> numbers;
map<int,int>::iterator inum;

numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
numbers[3] = 4;
numbers[4] = 5;

int count = 0;
for( inum = numbers.begin(); inum != numbers.end(); ++inum )
{
++count;
ch->printf( "Number %d:%d\r\n", inum->first, inum->second );
}
ch->printf( "Count #1: %d\r\n", count );

for( int x = 0; x < 900; ++x )
{
if( numbers[x] == 3 )
ch->print( "Number is 3!!\r\n" );
}

count = 0;
for( inum = numbers.begin(); inum != numbers.end(); ++inum )
{
++count;
ch->printf( "Number %d:%d\r\n", inum->first, inum->second );
}
ch->printf( "Count #2: %d\r\n", count );
}


Darien told me that checking a std::map for a certain value, like so: if( numbers[x] == 0 ) would cause the map to throw a default value into the map at key[x]. I didn't believe him because it sounded silly, but the above function when added as a test command to my codebase returned a Count #2 value of 900, instead of the expected 5.

Is this normal expected behavior for a std::map or is this a compiler bug that needs to be reported to GNU?
12 Jan, 2007, Davion wrote in the 2nd comment:
Votes: 0
This is totally normal. It's the functions of the overloaded operator that is [] ;). The purpose of the operator is to allow easy insertion of an element with it's key, if no element is defined, then the default value of that element is set at that key. If you want to check for the key, use find().
12 Jan, 2007, Guest wrote in the 3rd comment:
Votes: 0
Yeah, I suppose so, but then that needlessly complicates what should be a simple operation. And leads to a whole heap of potential bugs since none of the std::map resources I found ever explain that this is expected behavior.
12 Jan, 2007, Davion wrote in the 4th comment:
Votes: 0
http://msdn2.microsoft.com/en-gb/library... said:
Remarks

If the argument key value is not found, then it is inserted along with the default value of the data type.

operator[] may be used to insert elements into a map m using m[_Key] = DataValue; where DataValue is the value of the mapped_type of the element with a key value of _Key.

When using operator[] to insert elements, the returned reference does not indicate whether an insertion is changing a pre-existing element or creating a new one. The member functions find and insert can be used to determine whether an element with a specified key is already present before an insertion.
12 Jan, 2007, Omega wrote in the 5th comment:
Votes: 0
when using a std::map use its iterators to search over the data.

don't do a

for(x = 0; x < MAX_SKILL; x++)
{
if(ch->pcdata->learned[x] == 3)
return whatever;
}

do like this..

for(SkillsMap::iterator skill_iter = ch->pcdata->learned.begin(); skill_iter != ch->pcdata->learned.end(); ++skill_iter)      
{
if(skill_iter->second <= 0)
continue;

return skill_iter->second;
}


thats all i'm saying, only the values which have been 'set' will be used, instead of it parsing everything.

if you do a for loop through 900, it does create a default block for the map at that space, so to avoid this, you use the iterators to go over it. saves allot of time (points to the cpu usage saved on sstm in recent conversions) we nolonger search the whole MAX_SKILL crap anymore, aswell as a ton of other things.

another thing, when you do if(value[x] == whatever) it creates the key (x) and defaults a value, to avoid this, this function was created to stop it. it works like.

if(map_value(ch->pcdata->learned, sn) == 3)

or

x = map_value(ch->pcdata->learned, sn);

// basic method to keep the map from 'creating' empty values
// whilst allowing you to return what its 'second' is.
// Darien
template<typename Map>
typename Map::mapped_type
map_value( const Map & m, typename Map::key_type v )
{
typename Map::const_iterator it = m.find( v );
if ( it == m.end() )
return typename Map::mapped_type();
return it->second;
}


this will return the mapped_type, meaning, if it is an int, it will return 0, if it is a char *, it will return NULL, atleast its supposed to, as they are the 'defaults' for them.

ofcourse, they only return those when the key you were looking for was not located within the map.

else wise, it will return the second, so whatever value of learned[x] is storing. which is always a good thing.
12 Jan, 2007, Guest wrote in the 6th comment:
Votes: 0
Yep. Guess that template is going to have to do the trick. I still think whoever cooked up the logic behind the problem should be shot for being a dumbass. But that's just me. I seriously dislike having to write code that feels like I'm fighting the compiler for control.
12 Jan, 2007, Omega wrote in the 7th comment:
Votes: 0
I completely agree on that front, but they must of had a reason behind it. god only knows as to why.
13 Jan, 2007, kiasyn wrote in the 8th comment:
Votes: 0
you're not fighting the compiler you're fighting the STL.
13 Jan, 2007, Justice wrote in the 9th comment:
Votes: 0
Darien said:
I completely agree on that front, but they must of had a reason behind it. god only knows as to why.


The reason is simple. To behave like an array, the [] operator must be able to retrieve and modify the map. This is handled by returning the memory address of the value. In order to support inserts, any unknown key must be inserted so that the memory address is valid.
13 Jan, 2007, Omega wrote in the 10th comment:
Votes: 0
and there ya go, oddly enough, that was the reason i suspected.
0.0/10