views:

895

answers:

1

This time I'm able to show a complete code:

#include <unordered_map>
#include <iostream>
#include <stdlib.h>

using namespace std;

bool mystrcmp(const char *s1, const char *s2) {
        int i = 0;
        do {
                if(s1[i] != s2[i])
                        return false;
        } while(s1[i++] != '\0');
        return true;
}

struct eqstr
{
  bool operator()(const char* s1, const char* s2) const
  {
    return mystrcmp(s1, s2);
  }
};


int main(void) {
    char buffer[5] = {'h', 'e', 'd', 'e', '\0'};
    unordered_map<char *, int , hash<char *> , eqstr> int_from_symbols;
    int_from_symbols["hede"] = 1;
    int_from_symbols["hodo"] = 2;
    unordered_map<char *, int , hash<char *> , eqstr>::const_iterator it = int_from_symbols.find(buffer);
    eqstr myeq;
    if(myeq("hede",buffer))
     fprintf(stderr, "no problem here\n");
    if(it == int_from_symbols.end())
     fprintf(stderr, "dammit\n");
    else fprintf(stderr, "%d\n", int_from_symbols[buffer]);
    return 0;
}

This outputs:

no problem here
dammit

Any idea what's going on?

Thanks in advance,,
Onur

+2  A: 

The problem is that hash<char *> does not do what you want. It is not specialized to actually hash the 'string' but is simply returning the pointer as the hash.

Add this to your code and it will start working (although the hash function is not production quality and is for demonstration only):

namespace std
{
    template<>
    struct hash<char *> : public std::unary_function<char *, size_t>
    {
        size_t operator()(char* str) const
        { 
            size_t h = 0;
            for (; *str; ++str)
                h += *str;
            return h;
        }
    };
}
R Samuel Klatchko
I don't think that globally specializing `hash<char*>` for this is a good idea - among other things, this might make it very easy to break ODR. Why not just define a custom functor, and pass that as a template argument to `unordered_map`, as usual?
Pavel Minaev
Check your <functional> header for the hash<string> specialization.
Hans Passant
This is really annoying. I implemented other hash functions which encodes the structures as strings and used hash<char *> to hash those. Those hash functions worked correctly, if hash<char *> works incorrectly, why other ones worked correctly?
Onur Cobanoglu
OK, you are right. hash<char *> barely returns the pointer. Thank you for the answer, however, I need a good quality hash function for strings. Can you recommend me one?
Onur Cobanoglu
You should mark the answer as accepted if it turned out to be right.
Nicolás