【问题标题】:std::hash specialization using sfinae?使用 sfinae 的 std::hash 专业化?
【发布时间】:2015-07-03 19:58:55
【问题描述】:

作为一个练习,我试图看看我是否可以使用 SFINAE 为 std::pairstd::tuple 创建一个 std::hash 特化,当它的所有模板参数都是无符号类型时。我对它们有一点经验,但据我了解,散列函数需要已经用typename Enabled = void 模板化,以便我添加专业化。我真的不知道从这里去哪里。这是一个不起作用的尝试。

#include <functional>
#include <type_traits>
#include <unordered_set>
#include <utility>

namespace std {
template <typename T, typename Enabled = void>
struct hash<std::pair<T, T>, std::enable_if_t<std::is_unsigned<T>::value>>
{
    size_t operator()(const std::pair<T, T>& x) const
    {
        return x;
    }
};
}; // namespace std


int
main(int argc, char ** argv)
{
    std::unordered_set<std::pair<unsigned, unsigned>> test{};
    return 0;
}

错误:

hash_sfinae.cpp:7:42: error: default template argument in a class template partial specialization
template <typename T, typename Enabled = void>
                              ^
hash_sfinae.cpp:8:8: error: too many template arguments for class template 'hash'
struct hash<std::pair<T, T>, std::enable_if_t<std::is_unsigned<T>::value>>

这是我所期望的,因为我正在尝试将模板参数扩展为哈希......但我不确定当时处理这些情况的技术。谁能帮我理解一下?

【问题讨论】:

    标签: c++ c++14 template-specialization sfinae


    【解决方案1】:

    您不应该将std::hash 专门用于不依赖于您自己定义的类型的类型。

    也就是说,这个 hack 可能会奏效:

    template<class T, class E>
    using first = T;
    
    template <typename T>
    struct hash<first<std::pair<T, T>, std::enable_if_t<std::is_unsigned<T>::value>>>
    {
        size_t operator()(const std::pair<T, T>& x) const
        {
            return x;
        }
    };
    

    不过,真的,不要这样做。编写自己的哈希。

    【讨论】:

    • 有一个很好的理由不将 std::hash 专门用于对/元组:我真的希望在不久的某个时候自动组合哈希会出现在 std 中。
    • 这里为什么需要first?也就是说,为什么不std::enable_if_t&lt;std::is_unsigned&lt;T&gt;::value, T&gt;enable_if 不应该做 first 在这里所做的事情吗?
    • 不幸的是,这不适用于 clang godbolt.org/z/qjTMEvbse
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-21
    相关资源
    最近更新 更多