我正在从使用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/

10-13 00:04