unordered_map,IP地址作为密钥

时间:2014-03-30 16:14:05

标签: c++11 boost

我正在尝试在我的应用程序中构建链表的列表。该列表将包含唯一的IP地址,并且对于每个IP地址,我都有一个应用程序列表。我正在尝试使用unordered_map构建它,将Boost :: boost :: asio :: ip :: address作为键,将std :: list作为值:

#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;

稍后我尝试获取与IP地址关联的列表,如下所示:

APP_LIST *list = &user_map[ip];

但是我在编辑中遇到错误,所以请你指出问题是什么?

  1. 是否可以使用Boost:IPaddress作为关键功能?

  2. 另一个问题是可以使用char [some_size]作为键值吗?

  3. 错误输出:

    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]
    

3 个答案:

答案 0 :(得分:5)

这是我在简要检查ip::address的类接口后想出的内容。

我想指出,使用起来非常浪费。特别是如果您碰巧知道所有地址都是ipv4,例如我更喜欢按ulong键入。

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());
            }
        };
}

查看 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({ {}, {} });
}

答案 1 :(得分:2)

如果为IPaddress编写哈希函数,它将起作用。

答案 2 :(得分:2)

这是一个古老的问题,但是我最近在用c ++ 17编写游戏时遇到了同样的问题。

这是我解决的方法:

.text