unordered_map with IP address as a key

boost, c++11

Solution

Here's what I came up with after a brief inspection of the class interface for `ip::address`.

I would like to note that it's pretty wasteful to use. Especially if you happen to know that all addresses are ipv4, e.g. I'd prefer to key by `ulong` then.

namespace boost
{
    template <>
        struct hash<IPAddress>
        {
            size_t operator()(IPAddress const& v) const { 
                if (v.is_v4())
                    return v.to_v4().to_ulong();
                if (v.is_v6())
                {
                    auto const& range = v.to_v6().to_bytes();
                    return hash_range(range.begin(), range.end());
                }
                if (v.is_unspecified())
                {
                    // guaranteed to be random: chosen by fair dice roll
                    return static_cast<size_t>(0x4751301174351161ul); 
                }
                return hash_value(v.to_string());
            }
        };
}

See it Live on Coliru:

#include <boost/asio.hpp>
#include <boost/unordered/unordered_map.hpp>
#include <iostream>
#include <list>

typedef int                                                  ApplicationID;
typedef boost::asio::ip::address                             IPAddress;
typedef std::list<ApplicationID>                             APP_LIST;
typedef boost::unordered::unordered_map<IPAddress, APP_LIST> USER_MAP;

namespace boost
{
    template <>
        struct hash<IPAddress>
        {
            size_t operator()(IPAddress const& v) const { 
                if (v.is_v4())
                    return v.to_v4().to_ulong();
                if (v.is_v6())
                {
                    auto const& range = v.to_v6().to_bytes();
                    return hash_range(range.begin(), range.end());
                }
                if (v.is_unspecified())
                    return 0x4751301174351161ul;
                return hash_value(v.to_string());
            }
        };
}

int main()
{
    USER_MAP map;
    map.insert({ {}, {} });
}

Problem

I am trying to build a list of linked list in my application. The list will contains unique IP addresses,and for each IP addres I have a list of applications. I am trying to build it using unordered_map to take Boost::boost::asio::ip::address as a the key and std::list as value: ``` #include <boost/unordered/unordered_map.hpp> #include <iostream> #include <list> using namespace boost::asio::ip; using namespace std; typedef int ApplicationID; typedef address IPAddress; typedef list <ApplicationID> APP_LIST; typedef boost::unordered::unordered_map <IPAddress, APP_LIST> USER_MAP; USER_MAP user_map; ``` Later I try to get the list associated with an IP address as following: ``` APP_LIST *list = &user_map[ip]; ``` But I get errors in the compilation, so could you please specify what's the problem? Is it possible to use Boost:IPaddress as a key function? Another question is it possible to use char[some_size] as a key value? Error Output: ``` In file included from /boost/functional/hash/hash.hpp:535:0, from /boost/functional/hash.hpp:6, from /boost/unordered/unordered_map.hpp:21, from ipc_module.cpp:18: /boost/functional/hash/extensions.hpp: In member function ‘std::size_t boost::hash<T>::operator()(const T&) const [with T = boost::asio::ip::address, std::size_t = long unsigned int]’: /boost/unordered/detail/unique.hpp:331:55: instantiated from ‘boost::unordered::detail::table_impl<Types>::value_type& boost::unordered::detail::table_impl<Types>::operator[](const key_type&) [with Types = boost::unordered::detail::map<std::allocator<std::pair<const boost::asio::ip::address, std::list<int> > >, boost::asio::ip::address, std::list<int>, boost::hash<boost::asio::ip::address>, std::equal_to<boost::asio::ip::address> >, boost::unordered::detail::table_impl<Types>::value_type = std::pair<const boost::asio::ip::address, std::list<int> >, boost::unordered::detail::table_impl<Types>::key_type = boost::asio::ip::address]’ /boost/unordered/unordered_map.hpp:1192:26: instantiated from ‘boost::unordered::unordered_map<K, T, H, P, A>::mapped_type& boost::unordered::unordered_map<K, T, H, P, A>::operator[](const key_type&) [with K = boost::asio::ip::address, T = std::list<int>, H = boost::hash<boost::asio::ip::address>, P = std::equal_to<boost::asio::ip::address>, A = std::allocator<std::pair<const boost::asio::ip::address, std::list<int> > >, boost::unordered::unordered_map<K, T, H, P, A>::mapped_type = std::list<int>, boost::unordered::unordered_map<K, T, H, P, A>::key_type = boost::asio::ip::address]’ ipc_module.cpp:175:40: instantiated from here /boost/functional/hash/extensions.hpp:176:34: error: no matching function for call to ‘hash_value(const boost::asio::ip::address&)’ /boost/functional/hash/extensions.hpp:176:34: note: candidates are: /boost/smart_ptr/shared_ptr.hpp:708:33: note: template<class T> std::size_t boost::hash_value(const boost::shared_ptr<T>&) /boost/functional/hash/hash.hpp:144:24: note: std::size_t boost::hash_value(bool) /boost/functional/hash/hash.hpp:144:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘bool’ /boost/functional/hash/hash.hpp:149:24: note: std::size_t boost::hash_value(char) /boost/functional/hash/hash.hpp:149:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘char’ /boost/functional/hash/hash.hpp:154:24: note: std::size_t boost::hash_value(unsigned char) /boost/functional/hash/hash.hpp:154:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘unsigned char’ /boost/functional/hash/hash.hpp:159:24: note: std::size_t boost::hash_value(signed char) /boost/functional/hash/hash.hpp:159:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘signed char’ /boost/functional/hash/hash.hpp:164:24: note: std::size_t boost::hash_value(short int) /boost/functional/hash/hash.hpp:164:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘short int’ /boost/functional/hash/hash.hpp:169:24: note: std::size_t boost::hash_value(short unsigned int) /boost/functional/hash/hash.hpp:169:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘short unsigned int’ /boost/functional/hash/hash.hpp:174:24: note: std::size_t boost::hash_value(int) /boost/functional/hash/hash.hpp:174:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘int’ /boost/functional/hash/hash.hpp:179:24: note: std::size_t boost::hash_value(unsigned int) /boost/functional/hash/hash.hpp:179:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘unsigned int’ /boost/functional/hash/hash.hpp:184:24: note: std::size_t boost::hash_value(long int) /boost/functional/hash/hash.hpp:184:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘long int’ /boost/functional/hash/hash.hpp:189:24: note: std::size_t boost::hash_value(long unsigned int) /boost/functional/hash/hash.hpp:189:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘long unsigned int’ /boost/functional/hash/hash.hpp:195:24: note: std::size_t boost::hash_value(wchar_t) /boost/functional/hash/hash.hpp:195:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘wchar_t’ /boost/functional/hash/hash.hpp:202:24: note: std::size_t boost::hash_value(boost::long_long_type) /boost/functional/hash/hash.hpp:202:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘boost::long_long_type {aka long long int}’ /boost/functional/hash/hash.hpp:207:24: note: std::size_t boost::hash_value(boost::ulong_long_type) /boost/functional/hash/hash.hpp:207:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘boost::ulong_long_type {aka long long unsigned int}’ /boost/functional/hash/hash.hpp:215:36: note: template<class T> std::size_t boost::hash_value(T* const&) /boost/functional/hash/hash.hpp:308:24: note: template<class T, unsigned int N> std::size_t boost::hash_value(const T (&)[N]) /boost/functional/hash/hash.hpp:314:24: note: template<class T, unsigned int N> std::size_t boost::hash_value(T (&)[N]) /boost/functional/hash/hash.hpp:327:24: note: std::size_t boost::hash_value(float) /boost/functional/hash/hash.hpp:327:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘float’ /boost/functional/hash/hash.hpp:332:24: note: std::size_t boost::hash_value(double) /boost/functional/hash/hash.hpp:332:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘double’ /boost/functional/hash/hash.hpp:337:24: note: std::size_t boost::hash_value(long double) /boost/functional/hash/hash.hpp:337:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘long double’ /boost/functional/hash/hash.hpp:321:24: note: template<class Ch, class A> std::size_t boost::hash_value(const std::basic_string<Ch, std::char_traits<_CharT>, A>&) /boost/functional/hash/hash.hpp:343:24: note: std::size_t boost::hash_value(std::type_index) /boost/functional/hash/hash.hpp:343:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘std::type_index’ /boost/functional/hash/extensions.hpp:54:17: note: template<class A, class B> std::size_t boost::hash_value(const std::pair<_T1, _T2>&) /boost/functional/hash/extensions.hpp:63:17: note: template<class T, class A> std::size_t boost::hash_value(const std::vector<_Tp, _Alloc>&) /boost/functional/hash/extensions.hpp:69:17: note: template<class T, class A> std::size_t boost::hash_value(const std::list<_Tp, _Alloc>&) /boost/functional/hash/extensions.hpp:75:17: note: template<class T, class A> std::size_t boost::hash_value(const std::deque<_Tp, _Alloc>&) /boost/functional/hash/extensions.hpp:81:17: note: template<class K, class C, class A> std::size_t boost::hash_value(const std::set<_Key, _Compare, _Alloc>&) /boost/functional/hash/extensions.hpp:87:17: note: template<class K, class C, class A> std::size_t boost::hash_value(const std::multiset<_Key, _Compare, _Alloc>&) /boost/functional/hash/extensions.hpp:93:17: note: template<class K, class T, class C, class A> std::size_t boost::hash_value(const std::map<_Key, _Tp, _Compare, _Alloc>&) /boost/functional/hash/extensions.hpp:99:17: note: template<class K, class T, class C, class A> std::size_t boost::hash_value(const std::multimap<_Key, _Tp, _Compare, _Alloc>&) /boost/functional/hash/extensions.hpp:105:17: note: template<class T> std::size_t boost::hash_value(const std::complex<_Tp>&) /boost/functional/hash/extensions.hpp:177:9: warning: control reaches end of non-void function [-Wreturn-type] /boost/asio/error.hpp: At global scope: /boost/asio/error.hpp:244:45: warning: ‘boost::asio::error::system_category’ defined but not used [-Wunused-variable] /boost/asio/error.hpp:246:45: warning: ‘boost::asio::error::netdb_category’ defined but not used [-Wunused-variable] /boost/asio/error.hpp:248:45: warning: ‘boost::asio::error::addrinfo_category’ defined but not used [-Wunused-variable] /boost/asio/error.hpp:250:45: warning: ‘boost::asio::error::misc_category’ defined but not used [-Wunused-variable] ```

Original source