通常,如果新类型需要哈希,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.
所以有两个问题。
为什么会这样?应该已经声明了std::hash
的模板化版本。 (我唯一的猜测是它在一个更深层的命名空间中,它被转发)
这是标准行为吗?
编辑:回答问题1 - template<typename T> struct hash
已声明,但似乎无法在任何地方定义。这就是为什么我可以定义它。
答案 0 :(得分:1)
17.6.4.2.1命名空间std [namespace.std]
1如果C ++程序添加了声明或定义,则它的行为是未定义的 除非另有说明,否则
namespace std
或namespace std
内的命名空间 指定。程序可以为任何程序添加模板专业化 标准库模板仅在声明时namespace std
取决于用户定义的类型,专业化符合 原始模板的标准库要求,而不是 明确禁止。
由于您重新定义了namespace std
已存在的常规模板,因此您有未定义的行为。这包括@ T.C.在评论中提到,该计划工作正常。