为什么std :: hash是一个struct而不是一个函数?

Sci*_*llo 18 c++ std c++-standard-library c++11 stdhash

标准库将std :: hash实现为专门用于不同类型的模板结构.它是这样使用的:

#include <iostream>
#include <functional>

int main()
{
    std::hash<int> hasher;
    std::cout << hasher(1337) << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是这种设计选择背后的原因是什么.为什么它没有实现为模板函数并像这样使用:

#include <iostream>
#include <functional>

int main()
{
    std::cout << std::hash<int>(1337) << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Die*_*ühl 17

有多种原因,每种原因都足以满足选择:

  1. 您可以部分地专门化类模板,但是您只能使用完全专用的功能模板(至少到目前为止).因此,您可以std::hash<T>使用类模板替换整个相关模板参数.请注意,部分重载没有帮助,因为哈希函数需要以某种方式指定为无法通过重载函数完成的对象(除非它们是通过对象访问的,但这是区别对待的).
  2. 无序关联容器使用静态实体进行参数化(如果特定类型支持,也可以动态自定义),使用类模板更容易完成.
  3. 由于用于散列函数的实体是可自定义的,因此可以选择使用类型或函数指针进行自定义.函数指针通常难以内联,而类型的内联成员函数对于内联来说是微不足道的,从而提高了简单函数的性能,例如计算简单的散列.

  • 公平地说,默认哈希可以调用一个函数,然后可以为不支持的类型尝试调用`.hash()`方法,这将允许上面的所有内容,允许adl哈希(这比强制一个`更好). std`injection),并允许对象自己`哈希`,如果他们想.但这违反了KISS,即使它与"少"和"开始"的工作方式相匹配. (3认同)

mas*_*oud 5

模板函数不能部分专用于类型,而std::hash作为类模板专用于不同类型。

并且,在这种基于模板类的方式中,您可以进行一些元编程,例如访问返回类型和键类型,如下所示:

std::hash<X>::argument_type
std::hash<X>::result_type
Run Code Online (Sandbox Code Playgroud)