views:

66

answers:

3

Hi,

I have code such as this. I use

pvalueholder is class that is polymorphic , it can hold all sort of types, string..etc.. It also can have a type undefined.

typedef hash_map<pvalueholder,pvalueholder,pvaluehasher > hashtype;
hashtype h;
pvalueholder v;
v="c";
h[v]=5; // h has one element

pvalueholder v2=h[v]; // here h gets a new key/value how is that possible?
cout << (string) (h[v]) << endl; // here h gets another new key/value how is that possible?
int i =0;
for (hashtype::iterator h1=h.begin(); h1!=h.end();h1++)
{
  cout << "no: " << i++ << endl;
} // this prints three lines, it should print one...

Two values are undefined here, the third one is 5 as expected.

 size_t pvaluehasher::operator() (const pvalueholder& p) const
  {
      cout << "hashvalue:" <<  p.value->hashvalue() << endl;
   return p.value->hashvalue();

  }

returns Here is what is printed: hashvalue:84696444 hashvalue:84696444 hashvalue:84696444 returns:1 hashvalue:84696444 returns:1 hashvalue:84696444 returns:1 returns:1 hashvalue:84696444

Do you have any ideas what it may be? Thank you.

Solution: the function operator()(parameter1,parameter2) needs to be different in case of Microsoft STL. For microsoft, it needs to return less than relationship between parameter1 and parameter2. For gcc, it needs to return equality. I returned equality. The comparison function for the keys was not correct... The function returned true for equality while it has to return less than in case of Microsoft STL.

+2  A: 

My guess would be that your hash function is incorrect - meaning it produces different hash values given the same key "c".

Show the declaration for pvalueholder and full code for pvaluehasher.

Nikolai N Fetissov
Can an incorrect hash function cause the generation of new key even when reading an associative array?
Aftershock
I traced the hash function it seems to return the same number.
Aftershock
@Aftershock, "If the argument key value is not found, then it is inserted along with the default value of the data type", see http://msdn.microsoft.com/en-US/library/h90ew76k%28v=VS.80%29.aspx
Nick D
It is not so mysterious then
Aftershock
+1  A: 

It's almost impossible to comment on hash_map, because it's never been standardized, and the existing implementations aren't entirely consistent. Worse, your code doesn't seem to be correct or compilable as it stands -- some places the value associated with the key seems to be an int, and other places a string.

Using std::tr1::unordered_map and fixing the rest of the code to compile and seem reasonable, like this:

#include <unordered_map>
#include <iostream>
#include <string>

using namespace std;

typedef std::tr1::unordered_map<std::string, int> hashtype;

std::ostream &operator<<(std::ostream &os, std::pair<std::string, int> const &d) { 
    return os << d.first << ": " << d.second;
}

int main() {
    hashtype h;
    std::string v = "c";

    h[v]=5; // h has one element

    int v2=h[v]; 
    cout << h[v] << endl;
    int i =0;
    for (hashtype::iterator h1=h.begin(); h1!=h.end();h1++)
    {
      cout << *h1 << endl;
    } // this prints three lines, it should print one...

    return 0;
}

The output I get is:

5
c: 5

This seems quite reasonable -- we've inserted only one item, as expected.

Jerry Coffin
A: 

Solution: the function operator()(parameter1,parameter2) needs to be different in case of Microsoft STL. For microsoft, it needs to return less than relationship between parameter1 and parameter2. For gcc, it needs to return equality. I returned equality. The comparison function for the keys was not correct... The function returned true for equality while it has to return less than in case of Microsoft STL.

Aftershock