I was having problem declaring an iterator to traverse through a map and find values. I'm getting a error of "expected initializer before 'fibiter'".
map <int, int> fibHash;
int memoized_fib(int n)
{
map <int, int> iterator fibiter = fibHash.find(n); //ERROR HERE
if(fibiter != fibHash.end())
return *fibiter;
int fib_val;
if(n <= 1)
fib_val = 1;
else
fib_val = memoized_fib(n - 1) + memoized_fib(n - 2);
fibHash[n] = fib_val;
return fib_val;
}
int main()
[..]
You forgot to use the scope resolution operator, ::. The compiler thinks you declared a map<int, int> named iterator, and therefore gets mighty confused when it finds fibiter.
map<int, int>::iterator fibiter
is what you want
map <int, int> iterator → map <int, int>::iterator
iterator is a typedef defined within the class "map".
You can look that up on the implementation of the standard library shipped with GCC 4.6.3 in <bits/stl_map.h> line 139, you have:
typedef typename _Rep_type::iterator iterator;
As the typedef belongs to the definition of the class, you should add the ":" so that the compiler knows where to find it.
Related
I am trying to return a pair using an iterator from a map called map <int, vertex> nodemaphowever I am running into an error which says: error: invalid operands to binary expression ('std::map<int, vertex>::iterator' (aka '__map_iterator<typename __base::iterator>') and 'int') std::pair<int, vertex> node = *(it + v);
Below is my function code:
std::pair<int, vertex> Graph::getMap(int v)
{
std::map <int, vertex>::iterator it = nodemap.begin();
std::pair<int, vertex> node = *(it + v);
return node;
}
I am assuming that pointer arithmetic is possible and a map is composed of pairs as mentioned in this Stack Question.
Thank your for your help!
std::map returns a bidirectional iterator, which does not support addition. You can use std::advance(it, v);, however, I am not sure why you would want to increment a map::iterator like that. If you want to retrieve the vertex with the key v you would use:
std::map <int, vertex>::iterator it = nodemap.find(v);
The error come from this line:
std::pair<int, vertex> node = *(it + v);
std::map::iterator is bidirectional which means it can use ++ and -- on it.
In order to use "iterator + intValue", the iterator should be a Random Access iterator. Which is not the case with std::map
I am getting the compiler error:
error: request for member 'first' in 'list.std::map::operator[],
std::less, std::allocator > > >((* &0.0)).std::pair::second', which is
of non-class type 'int' int closestX = list[0].second.first;
when trying to read data from a map called list defined and with iterator as:
map<double, pair<int, int>> list;
map<double, pair<int, int>>::iterator it = list.begin();
Members in list are inserted with:
list.insert(it, pair<double, pair<int, int>>(findDistance(posr,posc,j, i), pair<int, int>(j, i)));
I am reading the value from the map using:
int closestX = list[0].second.first;
int closestY = list[0].second.second;
The error seems to indicate that the return type of list[0].second.first is non class type int, but that return type matches perfectly with the value type of closestX, and I have now hit a wall. Assume list[0] is initialized and holds a valid value.
list[0] is already of value type pair<int, int>, not of the iterator type. So you could write
int closestX = list[0].first;
int closestY = list[0].second;
The error seems to indicate that the return type of list[0].second.first is non class type int
No, the error message is telling that list[0].second is not class type so you can not perform .first on it.
Note that std::map::operator[] will return the mapped_type.
Returns a reference to the value that is mapped to a key equivalent to key.
list => map<double, pair<int, int>>
list[0] => pair<int, int>
list[0].second => int
list[0].second.first => failed
I'm creating a std::map<int, int> in C++ that I'd prefer to have they keys sorted from highest to lowest instead of the default sort order. My research lead me to std::greater which looked promising but when trying to use it I'm getting a compile error:
invalid type argument of unary ‘*’ (have ‘int’)
My map declaration is:
std::map<int, int, std::greater<int> > numMap;
And the error is getting thrown from this function:
void Row::addNumber(int num, int pos) {
numMap.insert(num, pos);
}
Answers to similar questions such as this include parenthesis in the declaration, i.e. std::greater() - but when I include those I get multiple errors regarding a function returning a function.
The problem – call of std::map::insert member function with invalid parameters: there are two integer values provided; but there must be std::pair<int, int>. Please see the reference: std::map::insert.
Preferable option
For convenience (just not to repeat the map type parameters), create a typedef for the map:
typedef std::map<int, int> IntMap;
The std::map has type definition for std::pair (pair representation) – std::map::value_type.
So, for example, if there is a std::map<int, int> the std::map::value_type would be std::pair<int, int>.
Use the std::map::value_type constructor (IntMap::value_type in this case):
class Row {
public:
void Row::addNumber(int num, int pos)
{
m_numMap.insert(IntMap::value_type(num, pos));
}
private:
typedef std::map<int, int> IntMap;
IntMap m_numMap;
};
Alternatives:
Use std::make_pair() function:
#include <utility>
...
void Row::addNumber(int num, int pos)
{
numMap.insert(std::make_pair(num, pos));
}
Directly use std::pair constructor:
void Row::addNumber(int num, int pos)
{
numMap.insert(std::pair<int, int>(num, pos));
}
A bit more pedantic than Sergey's answer (which also definitely works), instead Use:
typedef std::map<int, int, std::greater<int> > MyMap;
MyMap numMap;
void Row::addNumber(int num, int pos)
{
numMap.insert(MyMap::value_type(num, pos));
}
The benefit being that if you change the type of the map, you have less code to change later. And much less likely but still possible, if the implementation of std::map changes its value_type from std::pair to something else (in a future version of the stl), you are impervious to that change.
How would you make an iterator as a key of hash_map?
How would you define it under gcc, Microsoft c++?
E.g.
vector<string>::iterator i;
hash_map<vector<string>::iterator, int> h;
or
list<string>::iterator i;
hash_map<list<string>::iterator, int> h;
THis gives an error as iterators are not predefined as string and other types are...
Blockquote
It is not a good idea to store vector's iterators of use them as keys in an associative container because vector's iterators are unstable, that is, they get invalidated on insert, remove, resize, push_back an so on (see Iterator invalidation rules).
Plain index is much safer in this regard:
hash_map<size_t, int> h;
You can convert an index to an iterator by simply:
size_t index = ...
std::vector<std::string> vec(...);
std::vector<std::string>::iterator i = vec.begin() + index;
And iterator back to index:
index = i - vec.begin();
FWIW:
using iterators in that way is NOT robust. Iterators get invalidates on certain operations that act on the container. Your hash_map keys will be invalidated from that moment.
I suggest using
hash_map<string, int> h;
or
vector<string*> i;
hash_map<string*, int> h;
or even
vector<shared_ptr<string> > i;
hash_map<shared_ptr<string>, int> h;
If you know what you're doing (e.g. if the iterators are taken from a non-modifiable container), you can try to exploit the fact that &*it should be unique for each element:
typedef std::string my_container;
typedef my_container::const_iterator my_iterator;
struct IteratorHasher
{
std::size_t operator()(const my_iterator & it) const
{
return hasher(&*it);
}
private:
std::hash<const char *> hasher;
};
Usage:
int main()
{
std::unordered_map<my_iterator, int, IteratorHasher> mymap;
std::string hello("hello");
mymap[hello.begin()] = 3;
}
I would like to search within a vector<std::pair<int, vector<int> > >. This won't work due to the vector parameters:
std::vector<std::pair<int, std::vector<int> > > myVec;
iterator = find(myVec.begin(), myVec.end(), i);
Search would be on the first std::pair template parameter (int), in order to get the vector associated with it.
std::vector<std::pair<int, std::vector<int> > > myVec;
This requires C++0x for the lambda expression:
typedef std::pair<int, std::vector<int>> pair_type
std::find_if(myVec.begin(), myVec.end(), [i](pair_type const& pair)
{ return pair.first == i; });
If you're not using C++0x then either roll out your own loop or use something like Boost.Phoenix/Boost.Lambda.
Or, for both cases, why not use std::map?
You could make do with the following (pretty ugly) functoid:
struct FindFirst {
FindFirst(int i) : toFind(i) { }
int toFind;
bool operator()
( const std::pair<int, std::vector<int> > &p ) {
return p.first==toFind;
}
};
using it like this ( I couldn't get bind2nd to work - that's why I used the c'tor ):
int valueToFind = 4;
std::find_if(myVec.begin(), myVec.end(), FindFirst(valueToFind));
I think what you would like is a map:
std::map< int, vector< int > > foo;
You can then add elements, search by key etc:
int key = 4; //This will be the key
vector<int> value(5, 4); //Fill some values (5 4's in this case) into the vector
foo[key]=value; //Adds the pair to the map. Alternatively;
foo.insert( make_pair(key, value) ); //Does the same thing (in this context)
Looking at the way you've done things though, you might be wanting a std::multimap (which allows multiple values to have the same key) Class docs here
You're trying to map an int to a vector of int.
So try map<int, vector<int> >.
The second template parameter of a vector is the allocator - your compiler can probably puzzle out what you wanted to say, the declaration is wrong anyway. What you probably want is some sort of map type, like iammilind suggested.