I want to use tuple consisting of int
,char
,char
in my unordered_map
. I am doing like this:
#include <string>
#include <unordered_map>
#include <cstring>
#include <iostream>
#include <tuple>
using namespace std;
tuple <int,char,char> kk;
unordered_map<kk,int> map;
int main()
{
map[1,"c","b"]=23;
return 0;
}
but this gives me following errors:
map.cpp:9:21: error: type/value mismatch at argument 1 in template parameter list for ‘template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> class std::unordered_map’
map.cpp:9:21: error: expected a type, got ‘kk’
map.cpp:9:21: error: template argument 3 is invalid
map.cpp:9:21: error: template argument 4 is invalid
map.cpp:9:21: error: template argument 5 is invalid
map.cpp:9:26: error: invalid type in declaration before ‘;’ token
map.cpp: In function ‘int main()’:
map.cpp:14:16: error: assignment of read-only location ‘"b"[map]’
What I am doing wrong in this?
The template arguments for an unordered_map looks like this:
std::hash
is not specialized for tuples (scroll down to Standard specializations for library types). Therefore you need to provide your own, something like this:And finally, as Benjamin Lindley answer already addresses, you need to use
std::make_tuple
:The code was grabbed from Using a std::tuple as key for std::unordered_map and here is the Live Example.
Here is a method to use tuple as a key for an unordered_map without using a hash specialization:
Output is:
For those using
boost
they can just reroute hashing to boost's implementation using thisFirst error:
As the error clearly says, the template parameter needs to be a type.
kk
is not a type, it is an object. Perhaps you meant to make it a typedef?Second error:
Two problems here. First, putting commas between values does not make a tuple out of them. You need to be explicit about it, either calling the constructor of your tuple type, or using a function which returns a tuple (e.g.
std::make_tuple
). Second, your tuple is expecting chars ('c','b'
), not strings ("c","b"
).As pointed out, std::hash is not specialized for tuples. However, if your tuple consists of standard hashable types like string and int, the following code from generic-hash-for-tuples-in-unordered-map-unordered-set will automatically add such support in c++11.
Just paste the code in a header file and include it whenever needed:
After reading a few other posts I ended up with this. It uses an efficient hash combination algorithm and doesn't specialize things in the
std
namespace. You'll need to do some more work if you want this code to work for any tuple of hashable elements in general.This works in C++11 and above. In C++03 you can use
boost::hash
instead ofstd::hash
.