为模板化的Key专门制定std::hash?

7

我正在尝试为我的自定义类型专门编写哈希函数,该类型是一个模板键。

我参考了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(至少不是已知类型的 typedef)。完成后,MyKey 的哈希值不应该只调用成员变量的哈希函数,而应该返回一个 hash_combine 值,其中包含这些成员变量的哈希值。已经有很多现有的问题解释了这一点。 - Tony Delroy
1个回答

4
你的代码存在几个问题:
你不能在std命名空间中放置新的定义或声明;只允许特化(例如std :: hash)。因此,你的MyKey模板应该移出std命名空间。
你的operator()签名不正确。MyKey不是类型名称,你需要明确参数化它。另外,运算符应标记为const。
std :: hash专业化应提供成员类型argument_type和result_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;
        }
    };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接