我正在使用Visual C ++ 2008将C ++程序从Windows构建转换为使用gcc 4.6.1在Linux上构建。有一个使用<unordered_map>
的模块。
#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
包含时,我不确定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>'
答案 0 :(得分:6)
Microsoft接受隐式转换为std::size_t
的方式是一种扩展。
GCC的方式,专门化std::tr1::hash
,是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;
}
};
}
}
答案 1 :(得分:2)
由于您的mystruct
是由用户定义的,因此您需要为unordered_map
提供哈希函数:
struct my_hash {
std::size_t operator()( mystruct & c ) const
{
return c.m_val;
}
};
std::tr1::unordered_map<mystruct, int, my_hash> my_map;