Insert value into vector in a list - c++

I have a specific list with vectors. i want to add a value to a vector. How can I do this?
Here is my code:
//creating the list with vectors
std::list< vector<string> > adjacencylist;
//adding some vectors to the list...
adjacencylist.push_back(std::vector<std::string>(1, "String"));
adjacencylist.push_back(std::vector<std::string>(1, "String"));
adjacencylist.push_back(std::vector<std::string>(1, "String"));
Now I want to add values to the vectors in the list...
I tried for this:
std::list< vector<string> >::const_iterator it = adjacencylist.begin();
(*it).push_back("Some more String");
I thought that this would work. So I could iterate over all vectors and insert the values that I want. But it does not work. Here the output of the compiler:
example.cpp: In function ‘int main(int, char**)’:
example.cpp:148:31: error: passing ‘const std::vector<std::basic_string<char> >’ as ‘this’ argument of ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >; std::vector<_Tp, _Alloc>::value_type = std::basic_string<char>]’ discards qualifiers [-fpermissive]
(*it).push_back("test");

Because you have declared it as a const_iterator you have made it such that what it references cannot be edited. When you call push_back you are attempting to edit the vector that it points to. You need to replace:
std::list< vector<string> >::const_iterator it = adjacencylist.begin();
(*it).push_back("Some more String");
with
std::list< vector<string> >::iterator it = adjacencylist.begin();
(*it).push_back("Some more String");
Read up on general constness here and there is more specific information on const_iterator here.

Use simply an iterator. Also you can use it -> push_back instead of (*it).push_back.
This is an example:
for (list< vector<string> > it = adjacencylist.begin(); it != adjacencylist.end(); ++it)
{
it -> push_back("Your std::string");
}

Related

Error with map and string conversion in c++

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.

copying vector of pair

I am trying to copy a vector of pair to another:
vector<pair<int,int>> vp = {pair<int,int>(1,1), pair<int,int>(2,2)};
vector<pair<int,int>> vp2;
for_each(vp.begin(), vp.end(), [vp2](pair<int,int> p){
if(/*some condition*/){
vp2.push_back(p);
}
});
I get this compiler error:
error: passing ‘const std::vector<std::pair<int, int> >’ as ‘this’ argument of ‘void std::vector<_Tp, _Alloc>::push_back(value_type&&) [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >, value_type = std::pair<int, int>]’ discards qualifiers
Using gcc 4.5.1 on ubuntu.
As an alternative to Konrad's answer; if the goal is simply to copy the elements of the first vector if they match a certain condition, would std::copy_if not be a better match?
vector<pair<int,int>> vp = {pair<int,int>(1,1), pair<int,int>(2,2)};
vector<pair<int,int>> vp2;
copy_if(vp.begin(), vp.end(), back_inserter(vp2), [](pair<int,int> p) { return /* some condition */; });
Copying is much easier than that:
vector<pair<int,int>> vp2(vp.begin(), vp.end());
or even:
vector<pair<int,int>> vp2 = vp; // or
vector<pair<int,int>> vp2(vp);
The error in your code is that you capture vp2 by value which effectively makes it const in your anonymous method, and you cannot call push_back on a const vector. The following should work:
for_each(vp.begin(), vp.end(), [&vp2](pair<int,int> p){vp2.push_back(p);});
But there’s no reason to use this instead of the simpler code.

Iterator for a container of a custom object

If I've built a class that I want to contain inside, for example a set, how would I iterate through said set? Could I say
std::set<customObject>::iterator it
I thought I could do that, but I'm getting the following series of errors...
drawing.h:110: error: no match for ‘operator=’ in ‘it = ((object*)this)->object::objects. std::vector<_Tp, _Alloc>::begin [with _Tp = object, _Alloc = std::allocator<object>]()’
/usr/include/c++/4.2.1/bits/stl_tree.h:225: note: candidates are: std::_Rb_tree_const_iterator<object>& std::_Rb_tree_const_iterator<object>::operator=(const std::_Rb_tree_const_iterator<object>&)
drawing.h:110: error: no match for ‘operator!=’ in ‘it != ((object*)this)->object::objects. std::vector<_Tp, _Alloc>::end [with _Tp = object, _Alloc = std::allocator<object>]()’
/usr/include/c++/4.2.1/bits/stl_tree.h:292: note: candidates are: bool std::_Rb_tree_const_iterator<_Tp>::operator!=(const std::_Rb_tree_const_iterator<_Tp>&) const [with _Tp = object]
drawing.h:111: error: ‘struct std::_Rb_tree_const_iterator<object>’ has no member named ‘sketch’
here's my code:
void draw_in_place()
{
place();
std::set<object>::const_iterator it;
for(it = objects.begin(); it != objects.end(); it++){
*it.draw_in_place();
}
}
((object*)this)->object::objects. std::vector<_Tp, _Alloc>::begin
objects is apparently a std::vector<object>, not a std::set<object>. You therefore need to use a std::vector<object>::const_iterator.
*it.draw_in_place();
This is incorrect: you need to dereference the iterator to access the element first, then use the element:
(*it).draw_in_place();
// or
it->draw_in_place();
I think (at least) one of your problems is this line:
*it.draw_in_place();
The compiler is interpreting this as
*(it.draw_in_place());
versus your intended
(*it).draw_in_place();
To fix this, consider using the arrow operator, as in
it->draw_in_place();
It's perfectly legal to store custom objects in an STL set, so long as they can be compared with the < operator by default. If they can't, you'll either need to define operator < on them, or provide a custom comparator to the set, or specialize std::less for your particular type.

Problem with STL map iterator copying

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.

"Forced constness" in std::map<std::vector<int>,double> >?

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.