Goofy
Goofy

Reputation: 5377

std::unordered_map and key built of multiple elements

I'd like to store in map objects wrapping network connections, where key should be IP address + port number.

My question is how should I handle such key with two elements?

I can define std::unordered_map<std::pair<std::string, uint16_t>, Connection>, but I'm not sure how should I implement hash object for it. Only naive implementation comes to my mind:

std::size_t operator() (const pair<std::string, uint16_t>& key) const
{
    std::hash<std::string> ip_hash;
    std::hash<uint16_t>    port_hash;

    return ip_hash (key.first) + port_hash (port.second);
}

I assume that simple addition of two hash values is rather bad idea. Are there any general rules that i should obey to when implementing hash functions?

(I know, that i can build a string from IP address and port number, but I'm just curious).

Upvotes: 3

Views: 641

Answers (3)

egur
egur

Reputation: 7960

Your hashing is mostly fine for non security practices. You can make it more robust this way:

struct ip_port_hash
{
    size_t operator() (const std::pair< std::string, uint16_t >& key) const
    {
        std::hash<const char*> ip_hash;
        std::hash<size_t>      size_t_hash;

        return size_t_hash( ip_hash (key.first.c_str()) + key.second);
    }
};

Upvotes: 0

yasen
yasen

Reputation: 1260

A trivial solution will be to append the uint16_t port number to the string, representing the IP address. Then you can use std:unordered_map<string, Connection>.

Upvotes: 1

Praetorian
Praetorian

Reputation: 109119

If using boost is an option, boost::hash_combine makes this really easy (otherwise the implementation is available on the linked page).

std::size_t operator()(const pair<std::string, uint16_t>& key) const
{
    std::size_t seed = 0;
    boost::hash_combine(seed, key.first);
    boost::hash_combine(seed, key.second);
    return seed;
}

Upvotes: 1

Related Questions