重新定义std :: hash模板结构

时间:2016-05-18 17:29:46

标签: c++ hash stl

通常,如果新类型需要哈希,std::hash必须是专用的。我编写了一个测试哈希库,并希望将它用于所有尚未由标准库专门化的类型。

我用gcc / 4.9.3和clang / 3.7.0尝试了以下内容。令我惊讶的是,它有效。

#include <utility>
#include <functional>
#include <iostream>

namespace std {

template<typename T>
class hash
{
    public:
        size_t operator()(const T & obj)
        {
            return 99;
        }
};
}

int main(void)
{
    int i = 10;
    std::pair<int, int> pi{22,33};

    std::hash<int> hi;
    std::hash<std::pair<int, int>> hpi;

    std::cout << "Hash of int: " << hi(i) << "\n";
    std::cout << "Hash of int pair: " << hpi(pi) << "\n";
    return 0;
}

整数的散列是整数本身(它是标准的库版本),并且该对的散列是99.

所以有两个问题。

  1. 为什么会这样?应该已经声明了std::hash的模板化版本。 (我唯一的猜测是它在一个更深层的命名空间中,它被转发)

  2. 这是标准行为吗?

  3. 编辑:回答问题1 - template<typename T> struct hash已声明,但似乎无法在任何地方定义。这就是为什么我可以定义它。

1 个答案:

答案 0 :(得分:1)

  

17.6.4.2.1命名空间std [namespace.std]

     

1如果C ++程序添加了声明或定义,则它的行为是未定义的   除非另有说明,否则namespace stdnamespace std内的命名空间   指定。程序可以为任何程序添加模板专业化   标准库模板仅在声明时namespace std   取决于用户定义的类型,专业化符合   原始模板的标准库要求,而不是   明确禁止。

由于您重新定义了namespace std已存在的常规模板,因此您有未定义的行为。这包括@ T.C.在评论中提到,该计划工作正常。