4

I've been developing using Visual Studio 2010, and then compiling a Linux 64 version on another machine. To cover the difference between the 2 different compilers/environments, we have conditional include statements:

#ifdef __linux__
#include <tr1/unordered_map>
#endif

#ifdef _WIN32
#include <unordered_map>
#endif 
using namespace std;  // covers std::unordered_map
using namespace std::tr1; // covers tr/unordered_map

unordered_map<string,string> map;

For unordered_map, I've been using this documentation: cplusplus.com, which shows an at() method to look up a key in the map. (Unlike the [] operator, this won't insert key into the map if not found.)

When I tried to compile the code on the Linux machine, gcc throws an error saying

test_map.cpp:18: error: 'class std::tr1::unordered_map, std::allocator >, std::basic_string, std::allocator >, std::tr1::hash, std::allocator > >, std::equal_to, std::allocator > >, std::allocator, std::allocator >, std::basic_string, std::allocator > > >, false>' has no member named 'at'

The version of gcc on this machine is:

g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)

I tried compiling on a newer install of Linux with version:

gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)

and got the same error.

So my question has 2 parts:

  • Is there a work around so I can still use the unordered_map.at() function?

  • Where would I find the API docs for Linux unordered_map so I can be aware of any other discrepancies? (I looked at GNU online docs but I could figure out where to find the API reference that shows class and functions.)

UPDATE

I learned a lot from the responses posted here, so thanks to all. us2012's answer explained how to work around the compile issue, but in the end, I switched to using boost::unordered_map as suggested by John Dibling. (I decided to take everyone's warnings about the experimental C++11 support seriously, as well as also not wanting to inadvertently force a compiler setting on clients who are using our library.) This gave me a clean compile in both Windows and Linux, and no code change was required (other than removing the reference to std and tr1). Also I switched to use http://cppreference.com site, which has straightened me out with other problems already as well. (Surprisingly, this site never came up in any of my Google searches for C++ API docs.)

Thanks again, for everyone's great explanations.

4

4 回答 4

5

你处于一个非常棘手的位置。

GCC 4.4.6 是 RHEL6 发行版中的内容,是 C++11 之前的版本。TR1 库早于 C++11,在标准化完成之前,许多引入 C++11 的组件都从 TR1 发生了重大变化。

unordered_map是这些组件之一。

在 TR1 的日子里,unordered_map没有at()会员功能。这存在于 C++11 规范中。

您的 VS2010 编译器正在使用 C++11 规范(至少在unordered_map某种程度上),但 GCC 4.4.6 没有 C++11 的概念。实际上,您正在针对 2 种不同的语言进行编译。

至少在某种程度上,它仍然是 C++,所以应该有机会找到一些共同点。对于它的价值,我认为我个人不会将 TR1 中的任何东西用于生产工作——但这​​就是我。

正如其他地方所建议的那样,要达到相同的效果,您可以find关键。

我认为你的底线是这样的。在 GCC 4.4 中,C++0x 支持(注意我不是说 C++11)是实验性的。如果是我,我不会将任何std=c++0x功能用于生产工作。我也不会将 TR1 用于生产工作。

这给你三个选择:

  1. 根本不要使用哈希映射
  2. 使用来自 Boost 的哈希映射,或其他有信誉的 3rd 方库
  3. 编写自己的哈希图。
于 2013-10-09T16:30:42.693 回答
4

GCC 4.4 已经支持这些特性作为-std=c++0x. 不需要tr1命名空间,include 可以是<unordered_map>.

无论哪种方式,都不要太随意using namespace,尤其是对于可能有相当大重叠的命名空间,这会成为一个大问题。有关使用命名空间的更多信息,请查看GOTW

于 2013-10-09T16:30:19.843 回答
2

对于unordered_map,我一直在使用这个文档:cplusplus.com,它显示了一个 at() 方法来查找地图中的一个键。

但你不是在使用unordered_map,你在使用tr1::unordered_map。那不是一回事。

您正在查看的文档是 2011 年发布的 C++11 标准库的一部分。您使用的 GCC 版本来自 2009 年。不出所料,GCC 4.4 不能正确支持 C++11。TR1与 C++11 不同,TR1 中的容器是早期的实验版本,不包含成员at()

无论如何,cplusplus.com 都是垃圾,你最好看看http://cppreference.com

有没有解决办法,所以我仍然可以使用 unordered_map.at() 函数?

std::tr1::unordered_map没有at()会员。您可以使用选项在 GCC 4.4 中启用对 C++0x(C++11 完成之前使用的“代号”)的实验性支持-std=c++0x,允许您使用 GCC 版本std::unordered_map,但要求客户端执行相同操作才能使用您的代码这不是一个好主意。坚持使用编译器版本正确支持的可移植特性。

我在哪里可以找到适用于 Linux unordered_map 的 API 文档,以便了解其他任何差异?(我查看了GNU 在线文档,但我可以找出在哪里可以找到显示类和函数的 API 参考。)

按照“标准 C++ 库手册”链接,然后是“API 和源文档”链接,然后是 4.4 版本的 API 参考链接

不要忘记检查正确的文档,无论是std::tr1::unordered_map还是std::unordered_map,这取决于您要使用的文档。

于 2013-10-09T16:58:53.110 回答
1

等效应该是:

mymap->find(key)->second

find()给你一个迭代器,所以你应该检查这不是mymap.end().

于 2013-10-09T16:20:35.120 回答