【问题标题】:Specializing std::hash for templated Key将 std::hash 专门用于模板化 Key
【发布时间】:2015-07-05 17:59:52
【问题描述】:

我试图为我自己的类型专门化散列,一个模板键。

我是基于cppreference

我收到编译错误“C++ 标准没有为这种类型提供哈希”。我想我只是做错了。编译器还能支持这种模板吗?

namespace std {
    template<typename SType, typename AType, typename PType>
    struct MyKey {
        const SType from;
        const AType consume;
        const PType pop;
    };

    template<typename SType, typename AType, typename PType>
    struct hash<MyKey<SType, AType, PType>> {
        size_t operator ()(MyKey const &key) {
            std::hash<SType>()(key.from);
            std::hash<AType>()(key.consume);
            std::hash<PType>()(key.pop);
        }
    };
}

【问题讨论】:

  • 你必须教编译器如何散列你的类型——不仅仅是MyKey,还有STypeATypePType 也是(至少那些不是 typedefs 的已知类型)。完成之后,MyKey 的散列不应该只是调用成员变量的散列函数,它应该返回一个包含这些成员变量散列的 hash_combined 值。有 很多 个现有问题可以解释这一点。

标签: c++ templates c++11 hash stdhash


【解决方案1】:

您的代码存在一些问题:

不允许将新定义或声明放入std 命名空间;只允许使用专业化(例如std::hash)。所以你的MyKey 模板应该移出std 命名空间。

您的operator() 签名不正确。 MyKey 没有命名类型,您需要明确地将其参数化。此外,运营商应标记为const

std::hash 特化应提供成员类型argument_typeresult_type

如果作为SType 等传入的类型没有现有的特化,您需要自己提供。

您不会从散列函数返回任何内容,只是计算其他类型的散列并丢弃它们的返回值。

将为具有自己的 std::hash 特化的类型编译的实现:

//moved out of std
template<typename SType, typename AType, typename PType>
struct MyKey {
    const SType from;
    const AType consume;
    const PType pop;
};

namespace std {
    template<typename SType, typename AType, typename PType>
    struct hash<MyKey<SType, AType, PType>>{
        //member types
        using argument_type = MyKey<SType,AType,PType>;
        //arguments specified         ^     ^     ^
        using result_type = std::size_t;

        result_type operator ()(argument_type const& key) const {
        //marked const                                      ^
            //these will fail if SType and friends don't have a std::hash specialization
            result_type s_hash = std::hash<SType>()(key.from);
            result_type a_hash = std::hash<AType>()(key.consume);
            result_type p_hash = std::hash<PType>()(key.pop);

            //in your actual code, you'll want to compute the return type from the above
            return p_hash;
        }
    };
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多