21

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

#include <iostream>
#include <functional>

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

    return 0;
}

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

#include <iostream>
#include <functional>

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

    return 0;
}
4

2 回答 2

18

有多种原因,每一个都足以让您做出选择:

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

模板函数不能部分特化为类型,而std::hash作为类模板特化为不同的类型。

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

std::hash<X>::argument_type
std::hash<X>::result_type
于 2013-11-24T19:26:59.303 回答