c++ 中用于自定义类型的哈希函数

hash function in c++ for a custom type

我尝试编写一些自定义函数,而不是允许在 unordered_set 模板中使用我的自定义结构。

我的结构是:

struct test_record {
    int value;
    std::string name;
};

和哈希运算符:

namespace std {

    template<> struct hash<test_record> {

        using argument_type = test_record;
        using result_type = size_t;

        size_t operator()(const test_record& r) const {

            const std::hash<std::string> str_hash_fn;
            const std::hash<int> int_hash_fn;

            const size_t result = str_hash_fn(r.name) ^ int_hash_fn(r.value);

            return result;
        }
    };
};

像这样使用它:

int main()
{

    std::unordered_set <test_record> myrecordsset;

    myrecordsset.insert({ 1, "one" }); // error!

}

但是编译器抛出错误信息:

1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\xstddef(91,22): error C2676: binary '==': 'const _Ty' does not define this operator or a conversion to a type acceptable to the predefined operator 1> with 1>
[ 1> _Ty=test_record 1> ] 1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\xstddef(90): message : while compiling class template member function 'bool std::equal_to::operator ()(const _Ty &,const _Ty &) const' 1> with 1> [ 1> _Ty=test_record 1>
] 1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\xhash(164): message : see reference to function template instantiation 'bool std::equal_to::operator ()(const _Ty &,const _Ty &) const' being compiled 1> with 1> [ 1>
_Ty=test_record 1> ] 1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\xmemory(1318): message : see reference to class template instantiation 'std::equal_to' being compiled 1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\xmemory(1318): message : see reference to variable template 'const bool is_empty_v >' being compiled 1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\unordered_set(30): message : see reference to class template instantiation 'std::_Uhash_compare<_Kty,_Hasher,_Keyeq>' being compiled 1>
with 1> [ 1> _Kty=test_record, 1>
_Hasher=std::hash, 1> _Keyeq=std::equal_to 1> ] 1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\xhash(342): message : see reference to class template instantiation 'std::_Uset_traits<_Kty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>' being compiled 1> with 1> [ 1>
_Kty=test_record, 1> _Hasher=std::hash, 1> _Keyeq=std::equal_to, 1> _Alloc=std::allocator 1> ] 1>E:\Development\Visual Studio\VC\Tools\MSVC.25.28610\include\unordered_set(65): message : see reference to class template instantiation 'std::_Hash,_Alloc,false>>' being compiled 1> with 1> [ 1>
_Kty=test_record, 1> _Hasher=std::hash, 1> _Keyeq=std::equal_to, 1> _Alloc=std::allocator 1> ] 1>E:\Development_Projects\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp(20): message : see reference to class template instantiation 'std::unordered_set,std::equal_to,std::allocator>' being compiled

有什么问题吗?为什么编译器需要 unordered_set 中的 equal_to 运算符?

集合的要点在于它不包含两个相同的对象。仅通过查看散列不能确定身份,因此您需要进行具体的相等性比较。 C++ 要求您为 class 显式定义相等性,以防您需要任何特殊行为。

添加这个应该可以解决问题:

namespace std {
    template<> struct equal_to<test_record> {
        using argument_type = test_record;
        using result_type = bool;
        constexpr bool operator()(const test_record &lhs, const test_record &rhs) const {
            return (lhs.name == rhs.name) && (lhs.value == rhs.value);
        }
    };
};