c ++ std :: tr1 :: hash :: operator()undefined?

Ted*_*ton 1 c++ gcc tr1 visual-c++ c++11

我正在使用Visual C++ 2008将C++程序从Windows构建转换为使用gcc 4.6.1在Linux上构建.有一个使用的模块<unordered_map>.在VC++中,似乎完全没问题

#include <unordered_map>

...



std::tr1::unordered_map<mystruct, int> my_map;
Run Code Online (Sandbox Code Playgroud)

我们实际上支持的编译器不仅仅是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;
Run Code Online (Sandbox Code Playgroud)

这有效.很公平.不过现在我还有另外一个问题.这是mystruct的定义:

struct mystruct
{
#ifdef __cplusplus
    inline operator size_t() const
    {
        return m_val;
    }
#endif
    unsigned int m_val;
};
Run Code Online (Sandbox Code Playgroud)

在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; 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以告诉我这应该如何工作?能够size_t在您想要可以清洗的类型上定义运算符似乎更优雅,但我愿意接受定义operator()on 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>'
Run Code Online (Sandbox Code Playgroud)

Pot*_*ter 6

微软的方式是接受隐式转换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; 
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)