我在boost变体中有两个结构,而变体是boost :: unordered_map的关键。我正在寻找实现hash和equals方法的解决方案,该方法将采用变体中的结构。 下面是一个实现的RouteHasher方法(它没有工作运行时(相同的关键参数不从地图中获取值)。如何实现一个哈希,它将采用哈希结构的两个成员?
struct v4RouteKey_t
{
uint8 ipv4[4];
uint32 val;
}
struct v6RouteKey_t
{
uint8 ipv6[16];
uint32 val;
}
typedef boost::variant < v4RouteKey_t, v6RouteKey_t > RouteKey;
typedef boost::unordered_map < RouteKey, RouteValue_t > RouteMap;
struct RouteHasher : public boost::static_visitor<std::size_t>
{
template<typename T>
std::size_t operator()(const T& x) const { return boost::hash<T>()(x); }
std::size_t operator()(const RouteKey& x) const { return
boost::apply_visitor(RouteHasher(), x); }
};
struct RouteEquals : public boost::static_visitor<bool>
{
template<typename T>
bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; }
template<typename T1, typename T2>
bool operator()(const T1& lhs, const T2& rhs) const { return false; }
bool operator()(const RouteKey& lhs, const RouteKey& rhs) const
{ return boost::apply_visitor(RouteEquals(), lhs, rhs); }
};
答案 0 :(得分:0)
您是否为boost::hash_value
和std::hash<>
类型实现了哈希(v4RouteKey_t
或v6RouteKey_t
)和相等?
添加它使它为我编译:
<强> Live On Coliru 强>
#include <boost/unordered_map.hpp>
#include <boost/variant.hpp>
#include <boost/array.hpp>
#include <boost/tuple/tuple.hpp>
#include <cstdint>
struct v4RouteKey_t {
boost::array<uint8_t, 4> ipv4; uint32_t val;
bool operator==(v4RouteKey_t const& other) const {
return ipv4 == other.ipv4 && val == other.val;
};
};
struct v6RouteKey_t {
boost::array<uint8_t, 16> ipv6; uint32_t val;
bool operator==(v6RouteKey_t const& other) const {
return ipv6 == other.ipv6 && val == other.val;
};
};
size_t hash_value(v4RouteKey_t const& key) { return key.val; }
size_t hash_value(v6RouteKey_t const& key) { return key.val; }
struct RouteValue_t {};
typedef boost::variant<v4RouteKey_t, v6RouteKey_t> RouteKey;
typedef boost::unordered_map<RouteKey, RouteValue_t> RouteMap;
int main() {
RouteMap map;
}
启用c ++ 17的库/编译器可以在没有boost的情况下完成所有这些:
<强> Live On Coliru 强>
#include <unordered_map>
#include <numeric>
#include <variant>
#include <array>
#include <tuple>
struct v4RouteKey_t {
std::array<uint8_t, 4> ipv4; uint32_t val;
bool operator==(v4RouteKey_t const& other) const { return std::tie(ipv4, val) == std::tie(other.ipv4, other.val); };
};
struct v6RouteKey_t {
std::array<uint8_t, 16> ipv6; uint32_t val;
bool operator==(v6RouteKey_t const& other) const { return std::tie(ipv6, val) == std::tie(other.ipv6, other.val); };
};
namespace std {
template <> struct hash<v4RouteKey_t> {
size_t operator()(v4RouteKey_t const& key) {
return std::accumulate(key.ipv4.begin(), key.ipv4.end(), size_t(key.val), [](size_t seed, uint8_t b) { return (seed*139) ^ b; });
}
};
template <> struct hash<v6RouteKey_t> {
size_t operator()(v6RouteKey_t const& key) {
return std::accumulate(key.ipv6.begin(), key.ipv6.end(), size_t(key.val), [](size_t seed, uint8_t b) { return (seed*139) ^ b; });
}
};
}
struct RouteValue_t {};
typedef std::variant<v4RouteKey_t, v6RouteKey_t> RouteKey;
typedef std::unordered_map<RouteKey, RouteValue_t> RouteMap;
int main() {
RouteMap map;
}