How to iterate a C++ map of maps - c++

I have a map of map
std::map< int, std::map<string, double> > myMap;
std::map< int, std::map<string, double> >::iterator itr;
Iterating it with:
itr = myMap.find(nodeI);
if (itr == myMap.end())
{
exit(1) ;
}
results in the error:
error: no match for âoperator=â in
âitr = ((const PushList*)this)->PushList::myMap.std::map&lt:_Key, _Tp, _Compare, _Alloc>::find
[with _Key = int, _Tp = std::map&lt:std::basic_string&lt:char, std::char_traits&lt:char>,
std::allocator&lt:char> >, double, std::less&lt:std::basic_string&lt:char,
std::char_traits&lt:char>,
std::allocator&lt:char> > >, std::allocator&lt:std::pair&lt:const std::basic_string&lt:char,
std::char_traits&lt:char>, std::allocator&lt:char> >, double> > >, _Compare =
std::less&lt:int>, _Alloc =
std::allocator&lt:std::pair&lt:const int, std::map&lt:std::basic_string&lt:char,
std::char_traits&lt:char>,
std::allocator&lt:char> >, double, std::less&lt:std::basic_string&lt:char,
std::char_traits&lt:char>,
std::allocator&lt:char> > >, std::allocator&lt:std::pair&lt:const std::basic_string&lt:char,
std::char_traits&lt:char>, std::allocator&lt:char> >, double> > > > >](((const
int&)((const int*)((int*)nodeI))))â
How can I iterate the map of map?

From the error you posted it can be seen that you are doing this from within a class member const function. Is there any chance that myMap happens to be a member of that class? If so, what you want is to use const_iterator instead. You should do it anyways, since you are not expecting to modify the contents of the iterated elements.

Related

Unable to use integer edge weights with Kamada-Kawai layout

The question started here, but after all the updates it is already a different question with a different title.
My Graph type is defined as follows:
using Graph = boost::adjacency_list<vecS, setS, undirectedS, State, CostType>;
where CostType happens to be int.
I am trying to obtain the Kamada-Kawai spring layout as follows:
template <class PointMap>
PointMap layout() const {
PointMap res;
boost::associative_property_map<PointMap> temp(res);
circle_graph_layout(g_, temp, 10.0);
// https://stackoverflow.com/q/33903879/2725810
// https://stackoverflow.com/a/8555715/2725810
typedef std::map<VertexDescriptor, std::size_t> IndexMap;
IndexMap mapIndex;
associative_property_map<IndexMap> propmapIndex(mapIndex);
// http://www.boost.org/doc/libs/1_59_0/libs/graph/doc/bundles.html
kamada_kawai_spring_layout(g_, temp, get(edge_bundle, g_),
square_topology<>(50.0), side_length(50.0),
layout_tolerance<CostType>(),
CostType(1), propmapIndex);
return res;
}
gcc version 4.8.2 complains:
In file included from Graph.h:13:0,
from Astar.h:5,
from Test.cpp:4:
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp: In instantiation of ‘bool boost::detail::graph::kamada_kawai_spring_layout_impl<Topology, Graph, PositionMap, WeightMap, EdgeOrSideLength, Done, VertexIndexMap, DistanceMatrix, SpringStrengthMatrix, PartialDerivativeMap>::run() [with Topology = boost::square_topology<>; Graph = boost::adjacency_list<boost::vecS, boost::setS, boost::undirectedS, Pancake, int, boost::no_property, boost::listS>; PositionMap = boost::associative_property_map<std::map<void*, boost::convex_topology<2ul>::point, std::less<void*>, std::allocator<std::pair<void* const, boost::convex_topology<2ul>::point> > > >; WeightMap = boost::adj_list_edge_property_map<boost::undirected_tag, int, const int&, void*, const int, boost::edge_bundle_t>; EdgeOrSideLength = boost::detail::graph::edge_or_side<false, double>; Done = boost::layout_tolerance<int>; VertexIndexMap = boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >; DistanceMatrix = __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >; SpringStrengthMatrix = __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >; PartialDerivativeMap = boost::iterator_property_map<__gnu_cxx::__normal_iterator<boost::convex_topology<2ul>::point_difference*, std::vector<boost::convex_topology<2ul>::point_difference, std::allocator<boost::convex_topology<2ul>::point_difference> > >, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, boost::convex_topology<2ul>::point_difference, boost::convex_topology<2ul>::point_difference&>]’:
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp:524:20: required from ‘bool boost::kamada_kawai_spring_layout(const Graph&, PositionMap, WeightMap, const Topology&, boost::detail::graph::edge_or_side<EdgeOrSideLength, T>, Done, typename boost::property_traits<DistanceMap>::value_type, VertexIndexMap, DistanceMatrix, SpringStrengthMatrix, PartialDerivativeMap) [with Topology = boost::square_topology<>; Graph = boost::adjacency_list<boost::vecS, boost::setS, boost::undirectedS, Pancake, int, boost::no_property, boost::listS>; PositionMap = boost::associative_property_map<std::map<void*, boost::convex_topology<2ul>::point, std::less<void*>, std::allocator<std::pair<void* const, boost::convex_topology<2ul>::point> > > >; WeightMap = boost::adj_list_edge_property_map<boost::undirected_tag, int, const int&, void*, const int, boost::edge_bundle_t>; T = double; bool EdgeOrSideLength = false; Done = boost::layout_tolerance<int>; VertexIndexMap = boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >; DistanceMatrix = __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >; SpringStrengthMatrix = __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >; PartialDerivativeMap = boost::iterator_property_map<__gnu_cxx::__normal_iterator<boost::convex_topology<2ul>::point_difference*, std::vector<boost::convex_topology<2ul>::point_difference, std::allocator<boost::convex_topology<2ul>::point_difference> > >, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, boost::convex_topology<2ul>::point_difference, boost::convex_topology<2ul>::point_difference&>; typename boost::property_traits<DistanceMap>::value_type = int]’
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp:559:79: required from ‘bool boost::kamada_kawai_spring_layout(const Graph&, PositionMap, WeightMap, const Topology&, boost::detail::graph::edge_or_side<EdgeOrSideLength, T>, Done, typename boost::property_traits<DistanceMap>::value_type, VertexIndexMap) [with Topology = boost::square_topology<>; Graph = boost::adjacency_list<boost::vecS, boost::setS, boost::undirectedS, Pancake, int, boost::no_property, boost::listS>; PositionMap = boost::associative_property_map<std::map<void*, boost::convex_topology<2ul>::point, std::less<void*>, std::allocator<std::pair<void* const, boost::convex_topology<2ul>::point> > > >; WeightMap = boost::adj_list_edge_property_map<boost::undirected_tag, int, const int&, void*, const int, boost::edge_bundle_t>; T = double; bool EdgeOrSideLength = false; Done = boost::layout_tolerance<int>; VertexIndexMap = boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >; typename boost::property_traits<DistanceMap>::value_type = int]’
Graph.h:112:61: required from ‘PointMap StateGraph<StateNeighbor>::layout() const [with PointMap = std::map<void*, boost::convex_topology<2ul>::point, std::less<void*>, std::allocator<std::pair<void* const, boost::convex_topology<2ul>::point> > >; StateNeighbor = StateNeighbor<Pancake>]’
Drawer.h:60:75: required from ‘Drawer<Graph>::Drawer(const Graph&) [with Graph = StateGraph<StateNeighbor<Pancake> >]’
Test.cpp:34:22: required from here
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp:313:96: error: no matching function for call to ‘boost::detail::graph::linear_solver<2ul>::solve(boost::detail::graph::kamada_kawai_spring_layout_impl<boost::square_topology<>, boost::adjacency_list<boost::vecS, boost::setS, boost::undirectedS, Pancake, int, boost::no_property, boost::listS>, boost::associative_property_map<std::map<void*, boost::convex_topology<2ul>::point, std::less<void*>, std::allocator<std::pair<void* const, boost::convex_topology<2ul>::point> > > >, boost::adj_list_edge_property_map<boost::undirected_tag, int, const int&, void*, const int, boost::edge_bundle_t>, boost::detail::graph::edge_or_side<false, double>, boost::layout_tolerance<int>, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >, __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >, boost::iterator_property_map<__gnu_cxx::__normal_iterator<boost::convex_topology<2ul>::point_difference*, std::vector<boost::convex_topology<2ul>::point_difference, std::allocator<boost::convex_topology<2ul>::point_difference> > >, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, boost::convex_topology<2ul>::point_difference, boost::convex_topology<2ul>::point_difference&> >::weight_type [2][2], boost::detail::graph::kamada_kawai_spring_layout_impl<boost::square_topology<>, boost::adjacency_list<boost::vecS, boost::setS, boost::undirectedS, Pancake, int, boost::no_property, boost::listS>, boost::associative_property_map<std::map<void*, boost::convex_topology<2ul>::point, std::less<void*>, std::allocator<std::pair<void* const, boost::convex_topology<2ul>::point> > > >, boost::adj_list_edge_property_map<boost::undirected_tag, int, const int&, void*, const int, boost::edge_bundle_t>, boost::detail::graph::edge_or_side<false, double>, boost::layout_tolerance<int>, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >, __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >, boost::iterator_property_map<__gnu_cxx::__normal_iterator<boost::convex_topology<2ul>::point_difference*, std::vector<boost::convex_topology<2ul>::point_difference, std::allocator<boost::convex_topology<2ul>::point_difference> > >, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, boost::convex_topology<2ul>::point_difference, boost::convex_topology<2ul>::point_difference&> >::deriv_type&)’
_difference_type delta = -linear_solver<Point::dimensions>::solve(dE_d_d, dE_d);
^
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp:313:96: note: candidate is:
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp:95:18: note: template<class Vec> static Vec boost::detail::graph::linear_solver<2ul>::solve(double (*)[2], Vec)
static Vec solve(double mat[2][2], Vec rhs) {
^
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp:95:18: note: template argument deduction/substitution failed:
/home/meir/boost_1_59_0/boost/graph/kamada_kawai_spring_layout.hpp:313:96: note: cannot convert ‘dE_d_d’ (type ‘boost::detail::graph::kamada_kawai_spring_layout_impl<boost::square_topology<>, boost::adjacency_list<boost::vecS, boost::setS, boost::undirectedS, Pancake, int, boost::no_property, boost::listS>, boost::associative_property_map<std::map<void*, boost::convex_topology<2ul>::point, std::less<void*>, std::allocator<std::pair<void* const, boost::convex_topology<2ul>::point> > > >, boost::adj_list_edge_property_map<boost::undirected_tag, int, const int&, void*, const int, boost::edge_bundle_t>, boost::detail::graph::edge_or_side<false, double>, boost::layout_tolerance<int>, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >, __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >, boost::iterator_property_map<__gnu_cxx::__normal_iterator<boost::convex_topology<2ul>::point_difference*, std::vector<boost::convex_topology<2ul>::point_difference, std::allocator<boost::convex_topology<2ul>::point_difference> > >, boost::associative_property_map<std::map<void*, long unsigned int, std::less<void*>, std::allocator<std::pair<void* const, long unsigned int> > > >, boost::convex_topology<2ul>::point_difference, boost::convex_topology<2ul>::point_difference&> >::weight_type [2][2] {aka int [2][2]}’) to type ‘double (*)[2]’
_difference_type delta = -linear_solver<Point::dimensions>::solve(dE_d_d, dE_d);
This message is too cryptic for me to understand. It has something to do with not being able to convert int [2][2] to double (*)[2]. Is this related to the fact that CostType is int? But why can't it be? I will very much appreciate help in understanding what I am doing wrong.
Indeed, the error indicates the weights must be doubles.
That's because the algorithm invokes a linear solver with the raw points, and that's failing because the weight type is not a real number type.
If you change
using CostType = double;
everything compiles fine. Live On Coliru
If you insist, you can use a transformation:
#include <boost/property_map/transform_value_property_map.hpp>
kamada_kawai_spring_layout(g_, temp,
boost::make_transform_value_property_map([](int i) -> double { return i; }, get(edge_bundle, g_)),
square_topology<>(50.0),
side_length(50.0),
layout_tolerance<double>(),
double(1),
propmapIndex);
If you don't want to use the lambda, use a functor:
struct to_double { double operator()(int i) const { return i; } };
kamada_kawai_spring_layout(g_, temp,
boost::make_transform_value_property_map(to_double(), get(edge_bundle, g_)),
square_topology<>(50.0),
side_length(50.0),
layout_tolerance<double>(),
double(1),
propmapIndex);

set_difference for a custom structure

I am trying to find the difference between the following two sets:
A = {(0,0), (0,1), (1,0), (1,1), (2,2)}
B = {(0,0), (0,1), (1,0), (1,1)}
The answer I am expecting is
A - B = {(2,2)}
I tried the following code. But I am stuck unable to compile. Can anyone point out the mistake I am making?
#include <vector>
#include <algorithm>
#include <iostream>
#include <utility>
using namespace std;
class compare
{
public:
bool operator()(const pair <int, int> elem1, const pair <int, int> elem2)
{
return ((elem1.first == elem2.first) &&
(elem1.second == elem2.second));
}
};
int main()
{
vector < pair<int, int> > v, va, vb;
va.push_back(make_pair(0,0));
va.push_back(make_pair(0,1));
va.push_back(make_pair(1,0));
va.push_back(make_pair(1,1));
va.push_back(make_pair(2,2));
vb.push_back(make_pair(0,0));
vb.push_back(make_pair(0,1));
vb.push_back(make_pair(1,0));
vb.push_back(make_pair(1,1));
vector < pair<int, int> >::iterator it, result;
result = set_difference (va.begin(), va.end(),
vb.begin(), vb.end(),
inserter(v, v.end()),
compare());
// for (it = v.begin( ) ; it != result; it++)
// cout << "(" << it->first << it->second << ")" << ", ";
// cout << endl;
return 0;
}
EDIT:
The compile error message is the following:
set_difference.cc: In function `int main()':
set_difference.cc:36: error: no match for 'operator=' in 'result = std::set_difference [with _InputIterator1 = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _InputIterator2 = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _OutputIterator = std::insert_iterator<std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _Compare = compare]((&va)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&va)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&vb)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&vb)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), std::inserter [with _Container = std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >, _Iterator = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >](((std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >&)(&v)), (&v)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >]()), (compare(), compare()))'
/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_iterator.h:587: note: candidates are: __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >& __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >::operator=(const __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >&)
(This is addressing the correctness of the algorithms, not the compilation problems.)
Read the documentation: The two input ranges already have to be sorted.
You also have to provide an output iterator for the result.
So do this:
std::sort(va.begin(), va.end(), compare());
std::sort(vb.begin(), vb.end(), compare());
set_difference(va.begin(), va.end(), vb.begin(), vb.end(),
std::back_inserter(v), compare());
Your compare function should also define a strict, weak ordering, not an equality comparison.
By the way, std::pair<S, T> and std::tuple<T...> already come with built-in lexicographic comparison, so you shouldn't usually need to define your own comparison, unless you want something exotic: std::sort(va.begin(), va.end()); etc.
OK, now with the error message posted it's clear what is the problem:
set_difference returns the output iterator, which in this case is an insert_iterator (constructed by your call to inserter). You try to assign it to result which is a vector iterator. This is a type mismatch.
The simplest solution would be to just omit that assignment and the iterator result because you don't need that iterator anyway; the results have been written to v.
Your expectation is wrong: A - B is the set of elements in A not also found in B, which in your case is the empty set because every element in A is also found in B. B - A would give the result you expect.

C++ stl map compiler problem with GCC/codeblocks

The following code supposedly works with VS 2008 but I'm having trouble around line 53
where:
portMap_.erase(it);
I'm using codeblocks/mingw/gcc 4.xx
#include<iostream>
#include<map>
#include<string>
using namespace std;
//defining a union that is used with newMap_
union uu
{
char c;
int i;
} u;
//Lets define two different maps
//The first parameter is key and second value
map<string, int> portMap_;
map<void *, uu> newMap_;
int main()
{
//first entry in portmap
portMap_["first"] = 1;
//example of using the iterator
map<string, int>::const_iterator it;
string z = "second";
it = portMap_.find(z); //not in the map so wont be found
if(it == portMap_.end())
{
portMap_[z] = 22; //add second element
}
//Add thrid element directly
z = "third";
portMap_[z] = 12345;
//Add 4th element by insert
portMap_.insert(pair<string,int>("fourth", 4444));
//Add 5th element by insert
portMap_.insert(pair<string,int>("fifth", 5555));
cout<<"\n** Printing the portmap_ values **"<<endl;
for(it = portMap_.begin(); it != portMap_.end(); ++it)
cout<<"Key = "<<it->first<<" Val = "<<it->second<<endl;
cout<<"\n** Removing fourth element **"<<endl;
z = "fourth";
it = portMap_.find(z);
portMap_.erase(it);
cout<<"\n** Printing the portmap_ values **"<<endl;
for(it = portMap_.begin(); it != portMap_.end(); ++it)
cout<<"Key = "<<it->first<<" Val = "<<it->second<<endl;
//Playing with New Map
cout<<"\n\nCreating New Map whose key is a void pointer"<<endl;
uu u_val1, u_val2;
void *val1, *val2;
u_val1.i = 70, val1 = &u_val1;
newMap_[val1]=u_val1;
val2 = val1;
map<void *, uu>::const_iterator it_new;
it_new = newMap_.find(val2);
if(it_new != newMap_.end())
{
u_val2 = it_new->second;
cout<<"Note that since u_val2 is a union you can print i or c as required"<<endl;
cout<<"val2 = "<<val2<<" value.c = "<<u_val2.c<<endl;
cout<<"val2 = "<<val2<<" value.i = "<<u_val2.i<<endl;
}
return 0;
}
Heres the error:
map_example\map_example.cpp||In function 'int main()':|
map_example\map_example.cpp|51|error: no matching function for call to 'std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::erase(std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> >&)'|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_map.h|566|note: candidates are: void std::map<_Key, _Tp, _Compare, _Alloc>::erase(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = int, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char,|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_map.h|581|note: typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::size_type std::map<_Key, _Tp, _Compare, _Alloc>::erase(const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = int, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_stri|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_map.h|596|note: void std::map<_Key, _Tp, _Compare, _Alloc>::erase(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator) [with _Key = std::basic_string<char, std::char_traits<char>, std::all|
||=== Build finished: 1 errors, 0 warnings ===|
Your iterator is defined as const. Try a non-const iterator.
You can also erase an element by simply using a key_type. In your example, it would be:
portMap_.erase(z);
Try change from map<string, int>::const_iterator it; to map<string, int>::iterator it.

stl vector::insert difference in Windows and linux?

there. I've searched my question around here but failed to find anything relevant.
This is the problem.
I have this code in the part of my program, doing kind of stupid sort by inserts.
I developed that in MSVS 2008 and it all worked fine, but when I tried to compile that with g++, it failed because of list::insert function below;
//...
pair<uint, double> NewElem(i, Prob.at(i));
bool inserted(false);
vector<pair<uint, double> >::const_iterator li = NewList.begin();
for ( vector<double>::const_iterator ji = BlocksMemory.begin() ; ji != BlocksMemory.end() ; ++ji)
{
if (NewElem.second <= *ji)
li += _SORT_BLOCK;
else
break;
}
for(;li != NewList.end() ; ++li)
{
if (NewElem.second > li->second)
{
NewList.insert(li, NewElem );
inserted = true;
break;
}
}
as one can see, li is const_iterator of NewList;
And NewElem has type pair with the same content type as NewList contents;
There you can see the response (unreadable):
main.cpp:447: error: no matching function for call to "std::vector<std::pair<unsigned int, double>, std::allocator<std::pair<unsigned int, double> > >::insert(__gnu_cxx::__normal_iterator<const std::pair<unsigned int, double>*, std::vector<std::pair<unsigned int, double>, std::allocator<std::pair<unsigned int, double> > > >&, std::pair<unsigned int, double>&)"
/usr/include/c++/4.4/bits/vector.tcc:106: note: candidates are: __gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> > std::vector<_Tp, _Alloc>::insert(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = std::pair<unsigned int, double>, _Alloc = std::allocator<std::pair<unsigned int, double> >]
/usr/include/c++/4.4/bits/stl_vector.h:850: note: void std::vector<_Tp, _Alloc>::insert(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, size_t, const _Tp&) [with _Tp = std::pair<unsigned int, double>, _Alloc = std::allocator<std::pair<unsigned int, double> >]
What can be the reason? And what is the possible solution?
The signature of the insert member function that you are trying to use is probably:
iterator insert( iterator, const value_type& );
But the first argument that you are passing to the function is a const_iterator, that cannot be implicitly converted to a non const iterator. That code should not have worked on VS either.
The simple solution is that if you intend to modify the container you use a non-const iterator: define li as std::vector< std::pair<uint,double> >::iterator li = NewList.begin();
Also, are you sure that you want to be inserting into a std::vector? For performance reasons, a std::list would be a better choice. Also, an insert on a list doesn't invalidate existing iterators as it does for a vector.

C++ STL:map search by iterator to another map

I'm trying to jump through some hoops to organize data in a special way. I'm including a simplified piece of code that demonstrates my pain.
I can't use boost.
I'm using the latest version of g++ in cygwin.
#include <iostream>
#include <map>
using namespace std;
int main () {
map< int,int > genmap;
map< int,int >::iterator genmapit;
map< map<int,int>::iterator,int > itermap;
// insert something into genmap
genmap.insert (make_pair(1,500) );
// find and return iterator.
genmapit=genmap.find(1);
// insert the iterator/int into itermap. Dies on each of the following 3 versions of this line.
//itermap[genmapit] = 600; // crash
//itermap.insert ( pair< map<int,int>::iterator,int >(genmapit,600) ); // crash
itermap.insert ( make_pair(genmapit,600) ); // crash
return 0;
}
So as you can see, I have 1 simple map, an iterator to that map and another map that has the first argument as an iterator to the first map.
It's clear from this:
Why can't I put an iterator in map?
That I can have an iterator as the second argument. However, the way shown above provides this:
$ make
g++ -c -o main.o main.cpp
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h: In member fun
ction `bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp =
std::_Rb_tree_iterator<std::pair<const int, int> >]':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_tree.h:871: instantiate
d from `std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _All
oc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::i
nsert_unique(const _Val&) [with _Key = std::_Rb_tree_iterator<std::pair<const in
t, int> >, _Val = std::pair<const std::_Rb_tree_iterator<std::pair<const int, in
t> >, int>, _KeyOfValue = std::_Select1st<std::pair<const std::_Rb_tree_iterator
<std::pair<const int, int> >, int> >, _Compare = std::less<std::_Rb_tree_iterato
r<std::pair<const int, int> > >, _Alloc = std::allocator<std::pair<const std::_R
b_tree_iterator<std::pair<const int, int> >, int> >]'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_map.h:360: instantiated
from `std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_
Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator, bool> std::
map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [wit
h _Key = std::_Rb_tree_iterator<std::pair<const int, int> >, _Tp = int, _Compare
= std::less<std::_Rb_tree_iterator<std::pair<const int, int> > >, _Alloc = std:
:allocator<std::pair<const std::_Rb_tree_iterator<std::pair<const int, int> >, i
nt> >]'
main.cpp:23: instantiated from here
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h:227: error: no
match for 'operator<' in '__x < __y'
make: *** [main.o] Error 1
"instantiated from here" tells me nothing and a web search gives me no info on this.
Does STL:map simply not allow for this? I can recode my app to work around this but it will be very inefficient and I would like to get this working. Is there another kind of pointer I can make for a map element I could use?
Thanks for your time.
You can't do this because std::map iterators are not random access iterators so aren't comparable with <.
Instead, you could use pointers to the value_type in the first map as a map key.
You have to learn to read the error messages. In particular look at the message that comes after the long-winded description where the error happened:
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h:227: error: no
match for 'operator<' in '__x < __y'
Map iterators are not comparable with less-than operator which the map uses by default.
I suppose you can provide a comparison function that compares the pairs pointed to by the iterator, since the iterators themselves cannot be easily compared in a meaningful way.
struct CompareIterator
{
template <class FirstIter, class SecondIter>
bool operator()(FirstIter lhv, SecondIter rhv) const
{
return *lhv < *rhv;
}
};
//usage with map:
map< map<int,int>::iterator,int, CompareIterator > itermap;
std::pair defines operator<. I also used two iterator types, since it might be possible the types are different (iterator and const_iterator)
map<Key, Value>
The map iterator as key element into another map is not possible because map expects operator < to be defined by default to the key. If the Key (in this case map iterator) is not defined then you need to pass a functor as a predicate function that provides the comparison of Key (map iterator).