vendredi 29 avril 2016

Hash for boost::tuple containing std::vector

I have this code:

template <typename ReturnType, typename... Args>
function<ReturnType(Args...)> memoize(const function<ReturnType(Args...)>& func)
{
    using noRef = boost::tuple<typename std::remove_reference<Args>::type...>;
    ...
    static unordered_map<noRef, ReturnType> cache;
    auto result = cache.emplace(
        noRef{ boost::make_tuple(args ...) }, ReturnType{});
    if (result.second) { //ALWAYS TRUE WITH vector!
    ...

And I defined these 2 specializations for computing the hash of boost::tuple and std::vector:

namespace boost {
    namespace tuples {

        namespace detail {

            template <class Tuple, size_t Index = length<Tuple>::value - 1>
            struct HashValueImpl
            {
                static void apply(size_t& seed, Tuple const& tuple)
                {
                    HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
                    boost::hash_combine(seed, tuple.get<Index>());
                }
            };

            template <class Tuple>
            struct HashValueImpl<Tuple, 0>
            {
                static void apply(size_t& seed, Tuple const& tuple)
                {
                    boost::hash_combine(seed, tuple.get<0>());
                }
            };
        } // namespace detail

        template <class Tuple>
        size_t hash_value(Tuple const& tuple)
        {
            size_t seed = 0;
            detail::HashValueImpl<Tuple>::apply(seed, tuple);
            return seed;
        }

    }
}

namespace std {
    template <typename T> struct hash<std::vector<T>>
    {
        size_t operator()(const std::vector<T>  & v) const
        {
            size_t seed = 0;
            for (auto it = v.begin(); it != v.end(); it++)
                boost::hash_combine(seed, *it);
            return seed;
            /* your code here, e.g. "return hash<int>()(x.value);" */
        }
    };
}

This is the first time that I try to write a custom hash, but (as you can see from the comment) even if I use always the same vector<T> then there is always a successful insertion while it works fine if I use always the same double,double for example.

Why this happens?

Aucun commentaire:

Enregistrer un commentaire