【问题标题】:unordered_map::emplace error in g++ v 3.4.4-999g++ v 3.4.4-999 中的 unordered_map::emplace 错误
【发布时间】:2013-12-06 00:15:49
【问题描述】:

我的朋友向我介绍了哈希表,作为一种轻松将字符串与整数关联起来的方法,因此我尝试在我当前的项目中使用 std::unordered_map 实现它们。代码示例如下所示(为简洁起见,未显示完整功能,标题也不显示;我相信问题不存在):

unordered_map <string,int> world::gentypetable(){
    unordered_map <string,int> hashtable;
    hashtable.emplace("Normal",0);
    hashtable.emplace("Fire",1);
    hashtable.emplace("Water",2);
    hashtable.emplace("Electric",3);
    hashtable.emplace("Grass",4);

但是,当我尝试使用 g++ 3.4.4-999 编译此代码时,我收到以下错误:

error: 'class std::unordered_map<std::basic_string,<char>, int>' has no member named 'emplace'

我怀疑这是因为编译器已经过时了。是这个原因,还是另有原因?如果是由于编译器的原因,是否有替代语法可以用来避免将其更新到当前版本的漫长过程?

【问题讨论】:

  • 如果您对编程非常感兴趣,我建议您更新您的工具链(包括编译器)。我不明白,为什么它很长,但是 g++ 3.4.4 现在已经很过时了,使用这个版本会很麻烦(4.8.2 是最新的版本)。
  • 感谢大家的快速回答,我很高兴看到它只是编译器的一个问题。我使用该版本是因为我使用的是 Cygwin,并且直到今天我一直认为它是最新的。您建议我升级到哪个环境,或者在 Cygwin 中更新编译器可以正常工作? (这就是为什么我提到了一个漫长的升级;Cygwin 的网站说至少需要一个小时。)
  • 对于 Windows 上的 gcc,我更喜欢 MinGW64。
  • 好的,MinGW64是共识还是有其他意见?另外,MinGW64 是否允许我创建独立的 Windows 应用程序(我认为在 Cygwin 中无法实现)?
  • 再次感谢大家提供的有用答案。

标签: c++ c++11 g++ unordered-map


【解决方案1】:

您使用的是旧的编译器。为了大家,尤其是使用旧编译器不可避免地会被杀死的小猫,请更新。

this question on how to install GCC on Windows。总之,通过the installer安装。

【讨论】:

  • 所以,我终于开始更新 GCC,并从链接的线程中找到了您针对各种操作系统的自定义构建。因为我仍在学习并且对 Cygwin 环境感到满意,所以我决定下载您的 Cygwin 4.8.0 定制版本。我已将其解压缩并留下了 mingw32 文件夹,但不知道如何从那里继续。您在 Windows 中提取的说明似乎不适用于 Cygwin。如果您能快速指导我该做什么,我将不胜感激。 (希望您收到通知;我会私信您,但似乎缺少 PM 系统。)
  • @Arnold for cygwin 你可以使用 Cygwin 的 setup.exe 来安装 MinGW-w64 GCC。但是如果你想使用我的构建,你应该将解压后的mingw32/bin 目录添加到 PATH 中。您可以通过调用i686-w64-mingw32-[gcc,g++,gfortran] 来调用交叉编译器。
  • 感谢您的快速回复。我按照这些说明放置了 mingw32 文件夹,这样我就有了c:/cygwin/mingw32,然后使用命令PATH=$PATH:/mingw32/bin。但是,当我调用 i686-w64-mingw32-g++ 时,编译器返回以下错误,这表明它仍在查看旧的 mingw32 库(显然存在):In file included from /usr/lib/gcc/i686-w64-mingw32/4.5.3/include/c++/unordered_map:35:0, from PDACA.cpp:3: /usr/lib/gcc/i686-w64-mingw32/4.5.3/include/c++/bits/c++0x_warning.h:31:2。还需要什么其他操作?
  • 在您的 github 页面上,我注意到有标记为“删除 multilib”的脚本;我需要运行那些吗?我指的相关链接:github.com/rubenvb/MinGW-w64-build-scripts
  • @Arnold:脚本用于构建二进制文件。你不需要那些。顺便说一句,“删除多库”选项只是一个 git 提交消息,而不是“标签”。另外,请实际阅读错误消息,看看它们告诉你该怎么做(见here
【解决方案2】:

是的,这是过时编译器的问题。但是问题不在于unordered_map,它在当时是作为自定义扩展实现的ext/hash_map。一些代码使用适当的定义来使名称保持一致。它刚刚正式进入c++11 的标准,但在很长一段时间以前它作为扩展在许多编译器中实现。

问题在于emplacemove 语义是相对较新的概念。它也为c++11 标准化,但只有大多数现代编译器支持它。

这就是为什么编译器可能识别并能够使用哈希映射,但不知道方法本身。

您可能可以尝试将emplace 换成普通的insert。它可能涉及创建不必要的临时对象,但这是向 STL 容器添加元素的非常传统的方法。

旁注:gcc 3.4.4 现在真的很老了,缺少一些关键的东西。与其较新的版本相比,它在优化算法方面也相当逊色。更新一下就好了。

【讨论】:

    【解决方案3】:

    我怀疑这是因为编译器已经过时了。

    是的。根据this bug report 的说法,该功能直到 4.8.0 版才实现。我有点惊讶你的编译器完全支持 C++11,因为它比那要早几年。

    是否有替代语法可用于避免将其更新到当前版本的冗长过程?

    你也许可以做类似的事情

    hashtable.insert({"Normal",0});
    

    如果你的编译器支持大括号初始化;或者有类似数组的语法

    hashtable["Normal"] = 0;
    

    请注意,如果密钥已存在,则它们的行为会有所不同;第一个什么都不做,而第二个替换现有值。

    【讨论】:

    • IMO 这并不奇怪,AFAIK 哈希映射非常接近于使其成为以前版本的标准(我认为是03)。这就是为什么许多旧的编译器提供类似于自定义扩展的东西。此外,它基本上是一种数据结构,因此可以为任何编译器版本实现它。 emplace 虽然是全新的语法。此外,任何新语法很可能都不起作用。
    • @luk32:事实上,类似的东西早在 2000 年代中期就存在于 STL、TR1 和 Boost 中。令我惊讶的是,它很早就以 C++11 形式存在(即std::unordered_map);但也许我只是感到惊讶,因为当时我并没有特别关注标准化流程。
    • 这可能是一些自定义代码。它的名字不同。名字我记得是hash_map。也许有人使用了here 之类的技巧。我很确定它们的命名方式与 unordered_map 不同,即使在 Visual Studio 中也是如此。在特定情况下,行为存在一些细微(或多或少)差异,因为规范确实不是一成不变的。
    【解决方案4】:

    unordered_map 是在 c++11 中引入的,你的编译器似乎是 2009 年的。

    另一种方法是使用它的boost variant,或更新编译器。

    【讨论】:

    • 问题不是unoredered_map,编译器会这么说。它是emplace
    • 你是对的,问题仍然是过时的编译器。所以产生的结果保持不变:提升或更新编译器。对我来说,使用遗留调用似乎不是最佳实践:)
    • emplace 做了一些不同的事情。我打电话给insert legacy 因为它和容器一样古老。后来没有添加,所以它应该可以工作。它并没有过时。有时切换编译器并不是那么容易。你建议他不提供unordered_map,而显然它提供了。它不提供 OP 用于将元素插入其中的方法,但还有其他选项。不过,我同意在这种情况下,更新的编译器是一个很好的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    相关资源
    最近更新 更多