我正在从使用Visual C++ 2008构建Windows的C++程序转换为基于gcc 4.6.1在Linux上构建的C++程序。有一个使用<unordered_map>
的模块。在VC++中,似乎完全可以
#include <unordered_map>
...
std::tr1::unordered_map<mystruct, int> my_map;
实际上,我们不仅支持gcc 4.6和VC++ 2008,而且还支持更多的编译器,因此使用纯C++ 2011代码是不可行的。 gcc对
#include <unordered_map>
感到不满,抱怨这是一个真正的蓝色c++ 2011包含文件,因此,要做这项工作的我要做的一件事情就是将include更改为#include <tr1/unordered_map>
...
std::tr1::unordered_map<mystruct, int> my_map;
这有效。很公平。现在,我遇到了另一个问题。这是mystruct的定义:
struct mystruct
{
#ifdef __cplusplus
inline operator size_t() const
{
return m_val;
}
#endif
unsigned int m_val;
};
在VC++ 2008中,这似乎和
std::hash
需要专门研究mystruct
一样多。另一方面,std::tr1::hash
不喜欢这样,至少在gcc 4.6.1上不这样。它拒绝链接,抱怨std::tr1::hash<mystruct>::operator()( mystruct ) const
未定义。我不确定在执行正确的tr1
include时,VC++是否会发生这种情况-也许它会抱怨同一件事?明天我会尝试,但是现在我所拥有的只是一个带有gcc的linux机器。现在,我必须这样做才能使其正常工作:namespace std {
namespace tr1 {
std::size_t hash<mystruct>::operator()( mystruct & c ) const
{
return c.m_val;
}
}
}
谁能启发我这应该如何工作?能够在要散列的类型上定义
size_t
运算符似乎要优雅得多,但是我愿意在operator()
上定义std::tr1::hash
。更新:
我按照建议尝试专门化整个哈希类。用gcc构建,我得到
myfile.cpp:41:12: error: specialization of 'std::tr1::hash<mystruct>' after instantiation
myfile.cpp:41:12: error: redefinition of 'struct std::tr1::hash<mystruct>'
/usr/include/c++/4.6/tr1/functional_hash.h:45:12: error: previous definition of 'struct std::tr1::hash<mystruct>'
最佳答案
微软接受隐式转换为std::size_t
的方式是一种扩展。
GCC专门用于std::tr1::hash
的方法是TR1实际定义的方法,TR1现在已在C++ 11中进行了标准化(当然,tr1::
部分已删除)。
MSVC仍应接受hash
专门化,并且当然都应接受作为Hasher模板参数传递的全新类。
更好的风格是专门整个类,而不仅仅是operator()
函数:
namespace std {
namespace tr1 {
template<>
struct hash< mystruct > {
std::size_t operator()( mystruct & c ) const
{
return c.m_val;
}
};
}
}
关于c++ - C++ std::tr1::hash::operator()未定义?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10477292/