I'm familiar with Python's dictionary function, and I'm assuming based on my research that C++'s map function is relatively similar. However I'm running into a "conversion" issue:
std::string dictionary(std::string inquiry){
std::map<std::string, std::string> mapK;
mapK["12th st. Oakland City Center"]="12th";
mapK["16th st. Mission"]="16th";
return mapK.find(inquiry);
}
This is a string function that should receive a string and then with the corresponding key return a string back to the main. Evidently there's an issue with the return statement.
error: could not convert 'mapK.std::map<_Key, _Tp, _Compare, _Alloc>::find<std::basic_string<char>, std::basic_string<char>, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, std::basic_string<char> > > >((*(const key_type*)(& inquiry)))' from 'std::map<std::basic_string<char>, std::basic_string<char> >::iterator {aka std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >}' to 'std::string {aka std::basic_string<char>}'
return mapK.find(inquiry);
std::map::find() returns iterator, specifically std::map::iterator.
The only thing you need to fix is to put a dereference:
return *mapK.find(inquiry);
Or even better, just use operator[]:
return mapK[inquiry];
Do note though that if inquiry is not in the map, it will return empty string. In case of find, it is straight undefined behavior.
Your problem is with the return type of find. It does not return the mapped type. Rather it returns an iterator.
The signature for find is iterator find( const Key& key ); (see here; there is also the const overload).
You should also check whether the key was found. So you could write something like
MapType::iterator i = mapK.find(inquiry);
if (i != mapK.end())
return i->second;
else
return ""; // or handle error some other way
Alternatively you could use the member access operator[], but this will insert a default constructed element in the map if the key is not found.
Related
This piece of code runs successfully and results "Character Found".
unordered_map<char,char> mp;
mp['a'] = 'b';
char b='b';
if(mp['a'] && mp['a'] == b)
cout<<"Character Found";
But the following code gives an error:
unordered_map<char,string> mp;
mp['a'] = "b";
string s="b";
if(mp['a']) && (mp['a'] == s))
cout<<"Character Found";
The error is :
could not convert 'mp.std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[]<char, std::__cxx11::basic_string<char>, std::hash<char>, std::equal_to<char>, std::allocator<std::pair<const char, std::__cxx11::basic_string<char> > > >('a')' from 'std::unordered_map<char, std::__cxx11::basic_string<char> >::mapped_type {aka std::__cxx11::basic_string<char>}' to 'bool'
if(mp['a']) && (mp['a'] == s)) cout<<"Character Found";
Why is it so that the unordered_map<char,char> works fine but fails in the case of unordered_map<char,string> in c++
The condition mp['a'] doesn't check if an element exists or not, it fetches the value for that key. And if no value exist then it will create a value-initialized value that it inserts into the map, and return that value.
That means mp['a'] will return a std::string object, and you can't use std::string as a boolean expression.
That makes the check mp['a'] kind of useless, in both cases. If you want to see if an element exist in a map, you need to find it, which adds a layer of complexity (or use contains if your standard library support that upcoming C++20 feature).
I'm trying to use Dynamic Programming to implement fibonacci. Here's my .h file:
#ifndef DYNAMICPROGRAMMING_H
#define DYNAMICPROGRAMMING_H
#include <map>
class DynamicProgramming
{
public:
DynamicProgramming ();
~DynamicProgramming ();
int Fibonacci(int value);
private:
};
#endif // DYNAMICPROGRAMMING_H
Here's the relevant part in my .cpp file:
int DynamicProgramming::Fibonacci(int value)
{
int result;
std::map<int,int>fibonacci_storage;
std::map<int,int>::iterator valueFinder;
if (value == valueFinder->second){
return fibonacci_storage[value];
}
if (value <= 2 ){
result = 1;
} else {
result = Fibonacci(value - 1) + Fibonacci(value - 2);
}
fibonacci_storage.insert(std::pair<int,int>(value,result));
return result;
}
My error is coming from this line: if (value == valueFinder->second). This is what it says:
could not convert '((DynamicProgramming*)this)->DynamicProgramming::fibonacci_storage.std::map<_Key, _Tp, _Compare, _Alloc>::find [with _Key = int, _Tp = int, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int> >, std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, int> >, std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]((*(const key_type*)(& value)))' from 'std::map<int, int>::iterator {aka std::_Rb_tree_iterator<std::pair<const int, int> >}' to 'bool'
It looks to me like this is a very simple error, but I'm not sure what all that stuff means. Can someone help me out, I'd really like to master this language, it seems like it would be very useful.
To check if a key exists in a C++ map, you can use std::map::count. It returns 0 (the key is absent) or 1 (the key is present).
To check if a value exists in a C++ map, I think that you have to iterate over all pairs.
It seems that your question is more about a compilation error though.
There are several issues in the code above.
Your iterator valueFinder is not iterating over anything. To iterate, you need to call the begin() method on a map.
The variable fibonacci_storage is basically useless because it is not a member of the object and thus there is a different instance of that variable for each call to the Fibonacci method.
Technically, you don't have to iterate because the indices of your Fibonacci sequence are the keys in the map, and the values of your Fibonacci sequence are the values in your map.
As far as I know the only way to search through maps values is to iterate through. If you are trying to see if the key exists then you can use
map.find()
There are several issues with your code.
The biggest one is not syntax, it's the placement of the cache: since fibonacci_storage is a local variable, each recursive invocation of Fibonacci will have its own cache, meaning that there would be no caching at all. You need to move fibonacci_storage into the private: section of your class.
As far as fixing the syntax goes, a common trick used to implement searching of cache is to store the result of [] in a reference, like this:
int DynamicProgramming::Fibonacci(int value)
{
int &result = fibonacci_storage[value];
if (result) {
return result;
}
if (value <= 2 ){
return (result = 1);
}
return (result = Fibonacci(value - 1) + Fibonacci(value - 2));
}
Variable result holds a reference to the value inside the map, so when you update it in one of the two assign-return statements the corresponding value inside the map gets updated automatically.
Demo.
valueFinder is just an iterator for the type std::map<int,int> that is not associated to any instance of that type.
To associate it to an instance (here fibonacci_storage) you have to assign it to that instance, i.e.
valueFinder = fibonacci_storage.begin();
Finding an element can be done with source
valueFinder = fibonacci_storage.find(value);
where value is the key you are searching for. Now you check if value is in the map:
if( valueFinder != fibonacci_storage.end() )
{
// value found
}
and you're done.
I have an STL map that I want to iterate through, and can't seem to get the code to work. The code is:
//PowerupInfo is a struct defined in this class's header file
std::map<std::string, PowerupInfo> powerups;
...populate powerups
std::map<std::string, PowerupInfo>::iterator iter;
for (iter = powerups.begin(); iter != powerups.end(); iter++) {
return iter->second.type ;
}
The error message I get is:
error: no match for 'operator=' in 'iter = (((const std::map<std::string, PowerupInfo, std::less<std::string>, std::allocator<std::pair<const std::string, PowerupInfo> > >)((const PowerupList)this)) + 24u)->std::map<_Key, _Tp, _Compare, _Alloc>::begin with _Key = std::string, _Tp = PowerupInfo, _Compare = std::less<std::string>, _Alloc = std::allocator<std::pair<const std::string, PowerupInfo> >'|
note: candidates are: std::_Rb_tree_iterator<std::pair<const std::string, PowerupInfo> >& std::_Rb_tree_iterator<std::pair<const std::string, PowerupInfo> >::operator=(const std::_Rb_tree_iterator<std::pair<const std::string, PowerupInfo> >&)|
So I would normally assume that the problem has to do with setting iter equal to something it doesn't like, as it's not finding a match for 'operator='. But why? Why wouldn't that assignment work?
EDIT:
Turns out the method WAS const, causing the reference to powerups to be const as well, causing the error. I was just doing a bad job reading my own code. Thanks guys!
Your map name is poweruplist not powerups (You are using this name in the for loop). If this is not the cause of the error, then it looks like you are for loop is in a function which accepts the map by const reference (or is a const member function of a class). In that case your type of iterator should be const_iterator and not iterator.
Reformatting error code to make it readable:
error: no match for 'operator=' in
'iter =
((
(const std::map<std::string, PowerupInfo>*)((const PowerupList*)this)
)
+ 24u
)->std::map<std::string, PowerupInfo>::begin()'
Does not look the error message to the code you supplied.
Please cut and past the code. Otherwise it is meaningless.
I have a nested set of ints but I cannot insert elements into the nested sets.
std::set<std::set<int> > centre_as_set = bitset_to_set(centre->second->bit_partitions);
std::set<std::set<int> >::iterator set_itr;
for ( set_itr = centre_as_set.begin(); set_itr != centre_as_set.end(); ++set_itr ) {
set_itr->insert(4);
std::set<int>::iterator node_itr;
for ( node_itr = set_itr->begin(); node_itr != set_itr->end(); ++node_itr ) {
std::cout << *node_itr;
}
}
}
The error is
Partition_standalone.cpp:612: error:
passing ‘const std::set, std::allocator >’
as ‘this’ argument of
‘std::pair, _Compare,
typename
_Alloc::rebind<_Key>::other>::const_iterator,
bool> std::set<_Key, _Compare,
_Alloc>::insert(const _Key&) [with _Key = int, _Compare = std::less, _Alloc =
std::allocator]’ discards
qualifiers
I can't quite decipher that template error, any help appreciated.
The elements in a set are not mutable and you are trying to use the non-const member function insert() on a const instance of std::set<int>. There is the following nice comment if you follow the iterator symbol to its declaration in stl_set.h:
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 103. set::iterator is required to be modifiable,
// but this allows modification of keys.
typedef typename _Rep_type::const_iterator iterator;
C++98 and C++03 allowed modification, but this is a defect and already fixed in non-ancient GCC versions and VC10. The mentioned defect report can be found here and will be incorporated into the next standard.
Use e.g. something like the following instead to add the value 4:
// Readability:
typedef std::set<int> IntSet;
typedef std::set<IntSet> IntSetSet;
// Helper:
IntSetSet add_value_to_sets(const IntSetSet& in, int i) {
IntSetSet ss;
IntSetSet::iterator set_itr;
for ( set_itr = in.begin(); set_itr != in.end(); ++set_itr ) {
IntSet s = *set_itr;
s.insert(4);
ss.insert(s);
}
return ss;
}
// ...
IntSetSet centre_as_set =
add_value_to_sets(bitset_to_set(centre->second->bit_partitions), 4);
Edit: This answer is wrong as per the comment of georg.
I dont have a compiler here, but the full declaration of std::set is:
template < class Key, class Compare = less<Key>,
class Allocator = allocator<Key> > class set;
The "Key" of the outermost set is "std::set". The Comparator is "std::less>", or short "operator<(set, set)" which is undefined. The compiler warns about this only on the first use/instantiation of the comparator.
I dont think there is a useful ordering/comparator for std::set's. You are better off using std::vector which doesnt order the elements and doesnt need a comparator.
Oh, and it is not allowed to change (at runtime) the set keys if this would affect the ordering. But that would be a runtime error, not a compile error.
Consider this program:
#include <map>
#include <vector>
typedef std::vector<int> IntVector;
typedef std::map<IntVector,double> Map;
void foo(Map& m,const IntVector& v)
{
Map::iterator i = m.find(v);
i->first.push_back(10);
};
int main()
{
Map m;
IntVector v(10,10);
foo(m,v);
return 0;
}
Using g++ 4.4.0, I get his compilation error:
test.cpp: In function 'void foo(Map&, const IntVector&)':
test.cpp:8: error: passing 'const std::vector<int, std::allocator<int> >' as 'this' argument of 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int, _Alloc = std::allocator<int>]' discards qualifiers
I would expect this error if I was using Map::const_iterator inside foo but not using a non-const iterator.
What am I missing, why do I get this error?
The keys in a map are constant. A map is a tree, and you can't just going around changing the keys or you'll break its invariants. The value_type of a map with Key and Value is std::pair<const Key, Value>, to enforce this.
Your design needs some changing. If you really need to modify the key, you need to remove the element, change its key, and re-insert it with the new key.
Also concerning your example specifically, you will get undefined behavior (if this did work). Your map is empty when you call foo, so the iterator returned by find will be m.end(); the element doesn't exist. But then you'd go on to modify this non-existent element: ka-boom. Whenever you find something, you should check that it was found before you attempt to use it.