c++11 - 我应该将用户定义类型的专用 std::hash 放在哪里

标签 c++11 hash unordered-set user-defined

我搜索了很多页,我想我已经知道如何编写 std::hash 了。但我不知道该把它放在哪里。

此处提供了一个示例 http://en.cppreference.com/w/cpp/utility/hash .

但是,我定义了我的类型 Instance在命名空间 ca在文件 instance_management.h 。我想使用unordered_set<Instance>在另一个类的同一个文件中 InstanceManager 。所以我编写了以下代码:

namespace std
{
    template <> struct hash<ca::Instance>
    {
        size_t operator()(const ca::Instance & instance) const
        {
            std::size_t seed = 0;
            // Some hash value calculation here.
            return seed;
        }
    };
} // namespace std

但是我应该把它放在哪里呢?我尝试了很多位置,但都失败了。

我使用的是Visual Studio 2013。我尝试将之前的代码放在某些位置,但都无法编译。

// location 1

namespace ca
{
    class Instance {...}
    class InstanceManager
    {
        // ... some other things.
        private unordered_set<Instance>;
    }
}

// location 2

最佳答案

有几种方法。

专业std::hash

在您的代码中,请确保您的 std::hash<Instance>特化紧接着 Instance类定义,然后使用 unordered_set使用它的容器。

namespace ca
{
    class Instance {...};

}

namespaces std {

    template<> hash<Instance> { ... };

}

namespace ca {

    class InstanceManager
    {
        // ... some other things.
        private unordered_set<Instance>;
    }
}

一个缺点是,当传递 std::hash<ca::Instance> 时,您可能会遇到有趣的名称查找干扰。到其他功能。原因是 ca 的所有模板参数的关联命名空间 ( std::hash )可以在名称查找 (ADL) 期间使用。此类错误很少见,但如果发生,则可能很难调试。

参见this Q&A了解更多详情。

将您的哈希值传递给 unordered_set

struct MyInstanceHash { ... };

using MyUnorderedSet = std:unordered_set<Instance, MyInstanceHash>;

在这里,您只需将自己的哈希函数传递给容器即可完成。缺点是您必须显式键入自己的容器。

使用hash_append

但是请注意,有 N3980标准提案目前正在等待审查。该提案具有更优越的设计,它使用通用哈希函数,该函数采用任意字节流通过其模板参数(实际的哈希算法)进行哈希

template <class HashAlgorithm>
struct uhash
{
    using result_type = typename HashAlgorithm::result_type;

    template <class T>
    result_type
    operator()(T const& t) const noexcept
    {
        HashAlgorithm h;
        using std::hash_append;
        hash_append(h, t);
        return static_cast<result_type>(h);
    }
};

用户定义的类 X 必须提供正确的 hash_append通过它,它将自己呈现为字节流,准备好由通用哈希器进行哈希处理。

class X
{
    std::tuple<short, unsigned char, unsigned char> date_;
    std::vector<std::pair<int, int>>                data_;

public:
    // ...
    friend bool operator==(X const& x, X const& y)
    {
        return std::tie(x.date_, x.data_) == std::tie(y.date_, y.data_);
    }

    // Hook into the system like this
    template <class HashAlgorithm>
    friend void hash_append(HashAlgorithm& h, X const& x) noexcept
    {
        using std::hash_append;
        hash_append(h, x.date_);
        hash_append(h, x.data_);
    }
}

有关更多详细信息,请参阅作者 @HowardHinnant 在 CppCon14 上的演示( slidesvideo )。完整源代码 authorBloomberg可用。

关于c++11 - 我应该将用户定义类型的专用 std::hash 放在哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32697636/

相关文章:

c++ - MFC UpdateAllViews 是阻塞还是非阻塞?

algorithm - 为什么我们不使用布谷鸟哈希

python - 为什么 sets,dicts,list 在 python 中是不可散列的

python - python调用so文件时如何在extern C中使用shared_ptr?

c++ - C++ 中是否有 'override' 说明符的反转?

php - 使用 PHP 的 crypt 的河豚盐的正确格式是什么?

hash - 为什么 hastable 的 rehash 复杂度在最坏的情况下可能是二次方的

C++ bool std::operator < 带有键 std::unordered_set<int,std::hash<int>> 的映射错误

c++ - 将新元素插入/放置到 unordered_map/unordered_set 时的提示

c++ - 编译时模板 `std::integral_constant` 计数器 - 如何实现它?