2

My friend introduced me to hash tables as a way to easily associate strings with integers, and so I tried to implement them in my current project using std::unordered_map. A sample of the code is shown below (the full function is not shown for brevity, nor is the header; I am confident the problem does not reside there):

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);

However, when I try to compile this code using g++ 3.4.4-999, I receive the following error:

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

I suspect that this is because the compiler is outdated. Is that why, or is there another reason? And if it is due to the compiler, is there an alternative syntax that could be used to avoid the lengthy process of updating it to the current version?

Theolodis
  • 4,977
  • 3
  • 34
  • 53
  • 2
    If you are seriously interested in programming, I would advise you to update your tool chain (including the compiler). I do not see, why it is lengthy, but g++ 3.4.4 is very outdated by now and you will have a lot of trouble using this version (version 4.8.2 is the most recent one). – Jan Henke Nov 21 '13 at 13:43
  • Thanks everyone for the quick answers, and I'm glad to see its simply an issue with the compiler. I'm using that version because I'm using Cygwin, and I had assumed until today that it was up to date. Which environment do you recommend I upgrade to, or would updating the compiler within Cygwin work fine? (That is why I mentioned a lengthy upgrade; Cygwin's site said it would take minimally an hour.) – Arnold Myers Nov 21 '13 at 13:52
  • For gcc on Windows I prefer MinGW64. – Jan Henke Nov 21 '13 at 14:10
  • Okay, is MinGW64 a consensus or are there other opinions? Also, would MinGW64 allow me to create stand alone Windows applications (which I don't think can be accomplished in Cygwin)? – Arnold Myers Nov 21 '13 at 14:23
  • And again, thank you to everyone for the helpful answers. – Arnold Myers Nov 21 '13 at 14:24
  • Cygwin and MinGw are the only gcc implementations for Windows I know of. Cygwin uses a translation layer between POSIX and Win32 APIs while MinGW implements the POSIX API using the Win32 API, both have their own advantage and disadvantage. – Jan Henke Nov 21 '13 at 14:25
  • @Jan MinGW(-w64) *does NOT* implement the POSIX API. It provides the Win32 API in its own headers compatible with GCC. – rubenvb Nov 21 '13 at 15:26
  • @Rubenvb it is possible to compile both POSIX and Win32 applications using MinGW, so one can surly say it imlements both APIs and creates a Win32 compatible PE binary. – Jan Henke Nov 21 '13 at 15:59
  • @Jan Then please show me where MinGW(-w64) hides most of [the POSIX headers](http://pubs.opengroup.org/onlinepubs/9699919799/idx/head.html), and more importantly, the implementation. You're wrong. MinGW is just GCC on Windows. Very little POSIX stuff is actually there. Only pthreads (as an external library), some printf stuff, and a very small part of ``. – rubenvb Nov 21 '13 at 16:26
  • @rubenvb you do see that you contraditct yourself? You list yourself POSIX interfaces that are available. Nobody spoke about full POSIX conformance, often the most commonly used parts are enough to use it. – Jan Henke Nov 21 '13 at 16:37
  • @Jan when you say "it is possible to compile [...] POSIX [...] applications using MinGW", you imply all (most) applications written against POSIX will work with MinGW(-w64). Nothing is more wrong. MinGW(-w64) does not implement the "most commonly used parts" at all. It is true though for Cygwin, where POSIX applications will compile and run as intended, because most, if not all, of POSIX is implemented, with the necessary trade-offs performance-wise... – rubenvb Nov 22 '13 at 08:33
  • If you want to debate semantics of what POSIX is, I'm not going to continue this discussion, and instead refer you to the proper [POSIX standard](http://pubs.opengroup.org/onlinepubs/9699919799/), so you can discover yourself the extent to which you are incorrect. – rubenvb Nov 22 '13 at 08:34
  • "imply" always means you interpret something not written there. You are free to have a different opinion, but stop telling people to be incorrect, based on your *interpretation* of what they said and stick to the facts. I was certainly be able to compile some of my applications written for POSIX systems. – Jan Henke Nov 22 '13 at 08:47

4 Answers4

1

unordered_map was introduced in c++11, your compiler seems to be from 2009.

An alternative could be to use the boost variant of it, or to update the compiler.

Theolodis
  • 4,977
  • 3
  • 34
  • 53
  • The problem is not `unoredered_map`, compiler would say so. It is `emplace`. – luk32 Nov 21 '13 at 13:54
  • You are right, still the problem is the outdated compiler. So the resulting consequence remains the same: boost or update the compiler. Using legacy calls seems not best practice to me :) – Theolodis Nov 21 '13 at 14:00
  • `emplace` does something different. I called `insert` legacy because it is as old as the container. Not added later, so it should work. It is not obsolete. Sometimes switching compiers is not so easy. And you suggest like his does not provide `unordered_map` while apparently it does. It does not provide the method OP uses for inserting element into it, while there are other options. Nevertheless, I agree newer compiler is a very good recommendation in this case. – luk32 Nov 21 '13 at 14:07
1

Yes it is the problem with outdated compiler. However the problem does not lie in unordered_map it was implemented as custom extension back then as ext/hash_map. Some codes used appropriate defines to make the names consistent. It just officially got into the standard for the c++11, but it was implemented in many compilers as extensions for quite some time before.

The problem is the emplace and move semantics are relatively new concept. It also got standarized for c++11 but only most modern compilers support it.

That is why the compiler might recognize and be able to use hash maps, but does not know the method itself.

You probably could try swapping emplace for plain ol' insert. It may involve creating unnecessary temporaries, however it is pretty legacy method of adding elements to STL containers.

Side note: gcc 3.4.4 is really old now, and lacks some crucial stuff. It is also quite inferior in terms of optimization algorithms compared to its newer releases. It would be good to update.

luk32
  • 15,812
  • 38
  • 62
1

I suspect that this is because the compiler is outdated.

Yes. According to this bug report that function wasn't implemented until version 4.8.0. I'm somewhat surprised that your compiler supports C++11 at all, since it's several years older than that.

Is there an alternative syntax that could be used to avoid the lengthy process of updating it to the current version?

You might be able to do something like

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

if your compiler supports brace-initialisation; or there's the array-like syntax

hashtable["Normal"] = 0;

Note that these have different behaviour if the key already exists; the first does nothing, while the second replaces the existing value.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • IMO it is not very surprising, AFAIK hash maps were very close to make it into the previous version of standard (`03` I think). That is why many old compilers provide something similar as custom extensions. Also it's basically a data structure, so it is possible to implement it for any compiler version. `emplace` is whole new syntax though. Also any new syntax won't work most probably. – luk32 Nov 21 '13 at 14:05
  • @luk32: Indeed, similar things existed in STL, TR1 and Boost back in the mid 2000s. My suprise is that it existed in the C++11 form (i.e. as `std::unordered_map`) that early; but perhaps I'm only surprised because I wasn't particularly following the standardisation process back then. – Mike Seymour Nov 21 '13 at 14:30
  • That would probably be some custom code. It was named differently. Names I remember it as `hash_map`. Maybe someone used a trick like [here](http://fgda.pl/post/7/gcc-hash-map-vs-unordered-map). I am quite sure they were named differently than `unordered_map`, even in visual studio. There were some minor (more or less) differences in behaviour in specific cases, as specification was indeed not set in stone. – luk32 Nov 21 '13 at 16:58
0

You're using an old compiler. Please update for the sake of everyone and especially the kittens who will inevitably be killed when you use the old compiler.

See this question on how to install GCC on Windows. In short, install via the installer.

Community
  • 1
  • 1
rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • So, I finally got around to updating GCC, and from the linked thread, found your custom builds for various operating systems. Because I'm still learning and am comfortable in the Cygwin environment, I decided to download your 4.8.0 custom build for Cygwin. I've extracted it and am left with the mingw32 folder, but don't know how to proceed from there. Your instructions for extraction in Windows didn't seem to apply to Cygwin. If you could quickly educate me on what to do, I'd appreciate it greatly. (Hopefully a notification reaches you; I would PM you but it seems SO lacks a PM system.) – Arnold Myers Dec 07 '13 at 06:53
  • @Arnold for cygwin you could just use Cygwin's setup.exe to install MinGW-w64 GCC. But if you want to use my build, you should just add the unpacked `mingw32/bin` directory to PATH. You can call the cross-compiler by invoking `i686-w64-mingw32-[gcc,g++,gfortran]`. – rubenvb Dec 07 '13 at 10:52
  • Thanks for the quick response. I followed those instructions by placing the mingw32 folder so that I had `c:/cygwin/mingw32` and then using the command `PATH=$PATH:/mingw32/bin`. However, when I invoke `i686-w64-mingw32-g++`, the compiler returns the following error, which suggests its still looking at the old mingw32 libraries (that apparently existed): `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`. What other action is required? – Arnold Myers Dec 07 '13 at 13:17
  • On your github page I noticed that there were scripts with the labeled purpose of "remove multilib"; do I need to run those? The relevant link that I am referring to: https://github.com/rubenvb/MinGW-w64-build-scripts – Arnold Myers Dec 07 '13 at 13:30
  • @Arnold: the scripts are for building the binaries. You don't need those. The "remove multilib" option by the way, is just a git commit message, not a "label". Also, please actually read the error messages, and see that they tell you what to do (see [here](http://stackoverflow.com/questions/12762155/c0x-warning-h312-error)) – rubenvb Dec 07 '13 at 14:19
  • I read the error message, and it seemed to indicate that it was trying to call 4.5.3 libraries rather than 4.8.0 libraries. I omitted the step of appending the `-std=c++0x` because I tried it already, and it resulted in the same compile error that was noted in the original question here. It's the exact same message and result as when compiling using the old command (`c++` or `g++`), which suggests the new compiler not being directed to the associated libraries properly. How would I go about fixing that? – Arnold Myers Dec 07 '13 at 14:44
  • @Arnold are you sure you are calling the compiler executable that you think you are? Try to figure that out with `which i686-w64-mingw32-g++`. Get rid of the other one, or prepend the `mingw32/bin` directory to PATH. – rubenvb Dec 07 '13 at 14:47
  • I renamed the `i686-w64-mingw32-g++` contained in `c:\cygwin\mingw32\bin` to `uniquename` and prepended `mingw32/bin` to PATH using `PATH = /mingw32/bin:$PATH`. When I used the command `uniquename PDACA.cpp test.exe`, I did not receive an error (indicating it found the file), but when I tried to run `test.exe`, I was notified that it didn't exist. I'm not sure what to make of that. – Arnold Myers Dec 07 '13 at 15:06
  • I managed to update everything with setup.exe. Everything points to the 4.8.2 libraries and it no longer has an issue with emplace() when compiling. Thanks for the guidance, it is much appreciated. – Arnold Myers Dec 08 '13 at 08:40