I tried to insert a value into a boost unordered_multimap using the following code but that didn't work since it doesnt compile. Why is there no access [] operator?
The insert() method doesn't work either?
#include <iostream>
#include <boost/unordered_map.hpp>
using namespace std;
int main()
{
typedef boost::unordered_multimap<
int,
boost::unordered_multimap<
int,
boost::unordered_multimap<int, int>
>
> unordered_map;
unordered_map _3d;
_3d[0][0][0] = 10;
_3d[0][0][0].insert(10);
cout << _3d[0][0][0] << endl;
}
Errors:
multimap.cpp||In function 'int main()':
multimap.cpp|19|error: no match for 'operator[]' in '_3d[0]'
multimap.cpp|21|error: no match for 'operator[]' in '_3d[0]'
||=== Build finished: 2 errors, 0 warnings ===
Neither unordered_multimap nor multimap supports operator[] because it's not well-defined what it would mean. The idea behind operator[] is that you could write myMap[key] to mean "the unique value associated with key in myMap." When dealing with a unordered_multimap, this isn't mathematically well-defined; there can be many key-value pairs with the same key in the multimap, and it's unclear which particular value you'd like to have.
From the example you gave, it seems like you really want to have a standard unordered_map rather than an unordered_multimap. If you're trying to use a map of map of maps to represent some higher-dimensional array, then you probably only want to have each coordinate map to one particular subspace. Replacing unordered_multimap with unordered_map should fix this.
Hope this helps!
boost::unordered_map doesn't appear to have operator[]. Use the lookup functions instead.
What reference are you using?
Related
I am trying to create a map, something like: [{11,"Jitendra", 15.5}, {12, "Pranay", 15.5}], where the data between first curly brackets becomes the key and between the second curly brackets becomes values. Whatever technique I am trying it results in error.
Please let me know how I can declare an STL map, insert and manipulate values?
Compound variables are usable as keys for a map as long as they are comparable with operator< (see std::less). The simplest case is using a std::pair:
std::map<std::pair<int, std::string>, int> mymap; // key: int, string; value: int
You can extend the concept with an arbitrary number of key elements by using std::tuple as introduced in C++11.
Both pairs and tuples bring their own comparator overloads (see e.g. for tuple here), so no further work is needed on your side if your tuple elements are comparable by-themselves and are happy with an ordering that gives precedence on the first, then the second, and so on, element of the pair/tuple. Use std::make_pair() or std::make_tuple() to conveniently create them. However, it also works like this (C++17):
std::map<std::tuple<int, int>, std::tuple<int, int>> foo;
// insert
foo[{1,2}] = {3,4};
// access
auto [v1, v2] = foo[{1,2}];
std::cout << v1 << ", " << v2 << std::endl;
To be most flexible, you can extend it even further by using a struct and providing a comparator for the map to order its elements. You can also do this if your compiler lives behind the moon and does not support C++11.
I'm trying to use std::map::operator[] to iterate over the values of a std::map with a range-based for loop, but the following doesn't compile:
#include <iostream> // cout, endl
#include <map> // map
#include <set> // set
using namespace std;
int main () {
using namespace std;
const map<int, set<int>> m {{2, {201, 202}}, {3, {301, 302}}};
for (int v : m[2])
cout << v << endl;
return 0;
}
Here's the compiler's error message:
Test.c++:18:19: error: no viable overloaded operator[] for type 'const map<int, set<int> >'
for (int v : m[2])
The followup question is, Given that there are two versions of at(), why aren't there two versions of []?
map::operator[] inserts a new element into the map if the key isn't found, hence it cannot be const, and cannot be called on a const map.
Use m.at(2) instead.
operator[] will do one of two things. It will find the element at that location if it exists and return it. If there is no element at that location, it will value-initialize it, and then return it.
As such, it is neither logically nor programmatically const.
While you may say "but there is an element 2", the constness of an operation depends only on the types of the arguments, not the value of the arguments. And m[int] isn't guaranteed to have a valid element there.
To fix this, you can replace m[2] with m.find(2)->second. This does undefined behavior if 2 is missing from the map, but if 2 is present it will evaluate to the same thing as m[2]. Alterantively, m.at(2) will again do the same thing if 2 is present as a key, and throw an exception if is not present.
As an aside, when working on such a problem, try breaking your code down into smaller pieces. m[2]; all by itself on a line will fail to compile. In fact, the error message told you that it could not find an operator[] -- that might have given you a clue what was wrong.
Your map m is declared const meaning that you can only call const functions on it.
std:map::operator[] is not a such function, since it will modify the map if the specified key is not found.
What you need is std::map::at, which is const so you can call it on your const map.
If I have a std::multimap<int, std::map<int, MyClass>> myMultimap how to I insert a class object MyClassA into the map with value 1 at multimap value 2?
It looks like I can do myMultimap.at(2).insert(std::pair<1,MyClassA>); in c++11 but I am using c++98 due to a library regression/incomparability out of my control.
I've also tried
myMultimap[2].insert(
std::make_pair(
myMultimap[2].end(),
myClassA
)
);
which gives: error: no match for ‘operator[]’ (operand types are ‘std::multimap<int, std::map<int, ns_namespace::MyClassType> >’ and ‘int’)| for both of the [...]'s.
I don't want to do something like myMultimap.insert(std::make_pair(2,std::make_pair(1,MyClassA)))
because if I understand correctly, this would make a new map in the multimap rather than assigning the class object to the existing map within the multimap.
It is a two stage process:
Locate the position in the outer map where you want to do something to the inber map. If necessary, insert a new element.
Update the inner map withthe appropriatevalue.
I don't know why the outer map us a multimap (they are rarely useful) so the exampke just uses the first entry:
auto it = mymultimap.lower_bound(2);
if (it == mymultimap.end() || it->first != 2) {
it = mymultimap.insert(
std::make_pair(2, std::map<int, MyClass>())).first;
}
(*it)[1] = MyClassA;
(typed on a mobile device: there are probably typos but the overall approach should work).
Basically, I need to find all matching anagrams to a word. What I was doing was using an array of size 26 to represent the letters in a word.
Ex:
abcdefg={1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
aaaaaaa={7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
This is how I'm creating the array.
//stringtemp is a C++ string representing the word.
//letters is a size 26 int array representing all the letters in the string.
for(int i=0;i<stringtemp.length();i++)
{
letters[stringtemp[i]-65]+=1;
}
And this is how I'm storing the array in the map.
dictionary[letters].push_back(stringtemp);
So, am I doing something wrong or is this impossible in C++. In all the other answers I found, they suggested to use a vector as the key, but that won't work in my case(I think.)
All of std::array<T, 26>, std::string and std::vector<T> are perfectly valid key types for a std::map, since they all define less-than comparison operators. Note that std::array<T, 26> is similar to std::tuple<T, T, ..., T>, and comparison is defined lexicographically, very similar to string comparison.
#include <array>
#include <map>
typedef std::array<unsigned int, 26> alphabet;
std::map<alphabet, std::string> dictionary;
dictionary[{{1, 0, ..., 8}}] = "hello";
With a bit more work, you can also make all of those types keys for an std::unordered_map, though you'll have to add a bit of boilerplate code from Boost (using hash_combine).
std::map allows you to provide a Compare operator in the constructor. You may need to provide such a Comparator in order for two arrays {1,....} and {1,....} to match since they may be different actual objects.
The key type in a map must have an operator< defined for it. You could define operator< for your array type, but there's a much simpler approach: sort the letters in each word into alphabetical order, and use that sorted string as the key.
I don't know how to use the hash function in C++, but I know that we can use hash_map. Does g++ support that by simply including #include <hash_map>? What is a simple example using hash_map?
The current C++ standard does not have hash maps, but the coming C++0x standard does, and these are already supported by g++ in the shape of "unordered maps":
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std;
int main() {
unordered_map <string, int> m;
m["foo"] = 42;
cout << m["foo"] << endl;
}
In order to get this compile, you need to tell g++ that you are using C++0x:
g++ -std=c++0x main.cpp
These maps work pretty much as std::map does, except that instead of providing a custom operator<() for your own types, you need to provide a custom hash function - suitable functions are provided for types like integers and strings.
#include <tr1/unordered_map> will get you next-standard C++ unique hash container. Usage:
std::tr1::unordered_map<std::string,int> my_map;
my_map["answer"] = 42;
printf( "The answer to life and everything is: %d\n", my_map["answer"] );
Wikipedia never lets down:
http://en.wikipedia.org/wiki/Hash_map_(C%2B%2B)
hash_map is a non-standard extension. unordered_map is part of std::tr1, and will be moved into the std namespace for C++0x. http://en.wikipedia.org/wiki/Unordered_map_%28C%2B%2B%29
The name accepted into TR1 (and the draft for the next standard) is std::unordered_map, so if you have that available, it's probably the one you want to use.
Other than that, using it is a lot like using std::map, with the proviso that when/if you traverse the items in an std::map, they come out in the order specified by operator<, but for an unordered_map, the order is generally meaningless.