1

我正在将 C++ 程序从使用 Visual C++ 2008 构建的 Windows 转换为使用 gcc 4.6.1 在 Linux 上构建。有一个模块使用<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 <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()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>'
4

2 回答 2

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; 
            }
        };
    }
}
于 2012-05-07T06:10:53.083 回答
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;
于 2012-05-07T06:07:55.160 回答