Hug*_*ues 11 c++ hash namespaces c++11
我不清楚C++ 11标准中hash<T>
应该定义用户定义的仿函数.
例如,在23.5.2 Header中<unordered_map>
,它显示:
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class unordered_map;
Run Code Online (Sandbox Code Playgroud)
这表明,默认情况下,hash<T>
在全局命名空间equal_to<>
中搜索,而在std
命名空间中搜索.
为什么名称空间hash<>
与equal_to<>
?之间存在差异?
(实际上,在http://www.cplusplus.com/reference/unordered_map/unordered_map/的描述中,都没有指定std
命名空间.)
因此,在hash<>
为用户类型定义仿函数时,是应该将它包含在namespace std { }
块中,还是可以保留在当前命名空间中?
如果代码没有using namespace std;
,那么STL容器如何unordered_map
知道在std
命名空间中查找hash<>
与基元类型相关联的预定义仿函数?看起来默认Hash = hash<Key>
会找不到这些.
对不起,如果这些都是愚蠢的问题..
首先,模板没有"参数依赖查找".因此hash<Key>
,无论是std
在全局命名空间中还是在全局命名空间中,都将始终引用相同的模板Key
.如果它已解析为不同翻译单元中的不同模板,则会因ODR违规而导致未定义的行为.仅这一点就表明,hash
在这里是指std::hash
,这是因为,如果unordered_map
被宣布是这样的:
namespace std {
template<class T> struct hash;
template <class Key,
class T,
class Hash = hash<Key>, // resolves to std::hash<Key> for all Keys
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class unordered_map;
}
Run Code Online (Sandbox Code Playgroud)
但是,标准头中声明的类型不需要在源代码中编写(它们原则上可以内置于编译器中,也可以通过其他魔法预编译).该标准要求每个标准头仅在其概要中声明类型,这意味着通过省略std::hash
声明,该标准允许一些假设的实现以避免上述命名空间污染.这解释了为什么在概要中没有看到上述声明.
为了进一步补充上述结论,我们转到§20.8.12类模板hash [unord.hash],其内容如下:
23.5中定义的无序关联容器使用类模板哈希的特化作为默认哈希函数.
本段指的是std::hash
我们可以从概要中推断出来的<functional>
.
底线:这是标准格式的不一致.存在许多不一致之处,因此这个具体案例并不令人惊讶.在这种情况下,人们必须通过推断出唯一合情合理的东西来理解其意图.
专业化.您在声明它们的命名空间中专门化模板.您被明确授予专门为您自己的类型标准模板的权利:
namespace std {
template<> struct hash<YourClass> {
// specialization goes here
};
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1069 次 |
最近记录: |