代码之家  ›  专栏  ›  技术社区  ›  Bgy

boost中以结构为键的boost变体::无序_映射

  •  1
  • Bgy  · 技术社区  · 7 年前

    我在boost变体中有两个结构,变体是boost::unordered\u映射的关键。我正在寻找解决方案来实现一个哈希和等于方法,该方法将采用变体中的结构。 下面是实现的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); }
    };
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   sehe    7 年前

    你实现了哈希吗( 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;
    }