【问题标题】:How do I specify a custom hash function explicitly for unordered_set by passing a named function?如何通过传递命名函数为 unordered_set 显式指定自定义哈希函数?
【发布时间】:2015-03-23 03:23:59
【问题描述】:

根据对this question 的公认答案,可以使用std 的特化来为用户定义的类型提供哈希函数。

#include <unordered_set>
#include <stdint.h>


struct FooBar {
    int i; 
};
namespace std {
    template <> struct hash<FooBar>
    {
        size_t operator()(const FooBar & x) const
        {
            return x.i;
        }
    };
}

int main(){
    std::unordered_set<FooBar> foo(0);
}

但是,documentation 似乎暗示自定义哈希函数也可以显式传递给构造函数,我想为这个哈希函数使用命名函数。

但是,我当前的尝试遇到了编译错误。

#include <unordered_set>
#include <stdint.h>

struct FooBar {
    int i; 
};

const size_t hashFooBar(const FooBar& foo) {
    return foo.i;
}

int main(){
    std::unordered_set<FooBar> foo(0, hashFooBar);
}

什么是正确的模板魔法和方法签名来完成这项工作?

【问题讨论】:

    标签: c++ c++11 hash


    【解决方案1】:

    您需要提供哈希器的类型,在您的情况下是函数指针。并且您的 FooBar 类型必须是相等可比的。或者等效地,您可以以与提供哈希器相同的方式提供相等谓词。

    #include <unordered_set>
    #include <stdint.h>
    
    struct FooBar {
        int i; 
    };
    
    bool operator==(const FooBar& x, const FooBar& y)
    {
        return x.i == y.i;
    }
    
    size_t hashFooBar(const FooBar& foo) {
        return foo.i;
    }
    
    int main(){
        std::unordered_set<FooBar, size_t(*)(const FooBar&)> foo(0, hashFooBar);
    }
    

    我还应该注意,提供“函子”而不是函数更受欢迎,因为前者可以内联,而后者可能不内联。

    #include <unordered_set>
    #include <stdint.h>
    
    struct FooBar {
        int i; 
    };
    
    bool operator==(const FooBar& x, const FooBar& y)
    {
        return x.i == y.i;
    }
    
    struct hashFooBar
    {
        size_t operator()(const FooBar& foo) const {
            return foo.i;
        }
    };
    
    int main(){
        std::unordered_set<FooBar, hashFooBar> foo(0);
    }
    

    【讨论】:

      【解决方案2】:

      除了Howard Hinnant's answer,它解释了如何同时传入函数指针和自定义首选(后者严格首选),您还可以像这样传入 lambda:

      bool operator==(const FooBar& x, const FooBar& y)
      {
          return x.i == y.i;
      }
      
      int main() {
          auto hash = [](const FooBar& foo) { return foo.i; };
          std::unordered_set<FooBar, decltype(hash)> set{0, hash};
      }
      

      这也可能内联散列函数,而函数指针版本肯定不会。您也可以通过打印尺寸来查看:

      std::unordered_set<FooBar, decltype(hash)> setLambda{0, hash};
      std::unordered_set<FooBar, int(*)(const FooBar&)> setFuncPtr{0, +hash};
      
      std::cout << sizeof(setLambda);   // prints 56
      std::cout << sizeof(setFuncPtr);  // prints 64, cause of the
                                        // extra function pointer
      

      【讨论】:

        猜你喜欢
        • 2020-08-27
        • 2018-06-07
        • 2012-11-09
        • 2020-08-23
        • 1970-01-01
        • 2013-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多