c++ problem with vector push_back - c++

UPDATE:
The following code gives me an error
Graph.cpp: In function 'std::ostream&
operator<<(std::ostream&, const
Graph&)': Graph.cpp:43: error: passing
'const std::map >,
std::less,
std::allocator > > > >' as
'this' argument of '_Tp&
std::map<_Key, _Tp, _Compare,
_Alloc>::operator[](const _Key&) [with _Key = long int, _Tp = std::vector >, _Compare =
std::less, _Alloc =
std::allocator > > >]'
discards qualifiers Graph.cpp:44:
error: passing 'const std::map >,
std::less,
std::allocator > > > >' as
'this' argument of '_Tp&
std::map<_Key, _Tp, _Compare,
_Alloc>::operator[](const _Key&) [with _Key = long int, _Tp = std::vector >, _Compare =
std::less, _Alloc =
std::allocator > > >]'
discards qualifiers make[2]: *
[build/Debug/GNU-MacOSX/Graph.o] Error
1
class Graph {
public:
Graph();
Graph(const Graph& orig);
virtual ~Graph();
void clear();
void rgg(lint, double);
bool is_directed() { return directed; }
friend ostream& operator<< (ostream&, const Graph&);
private:
map< lint, vector<lint> > adjList;
vector< pair<double, double> > xy;
double radius;
MTRand Rand;
bool directed;
};
void Graph::rgg(lint n, double r) {
radius = r; directed = false;
clear();
for(lint i = 0; i < n; i++)
xy.push_back(pair<double, double>(Rand.rand(), Rand.rand()));
}
ostream& operator<< (ostream& os, const Graph& inGraph) {
for(lint i = 0; i < inGraph.nodes; i++) {
os << i << " ";
if( inGraph.adjList.find(i) != inGraph.adjList.end() ) {
for(lint idx = 0; idx < (inGraph.adjList[i]).size(); idx++ )
os << inGraph.adjList[i].at(idx) << " ";
}
os << endl;
}
}
Thank you in advance,

I suspect that you mean Rand instead of MTRand:
Rand.rand()
MTRand is the name of the type. Rand is the name of the instance you created.

Just a guess, but did you try
xy.push_back(pair<double, double>(MTRand.rand(), MTRand.rand())
according to the declation of xy?
EDIT: seems the OP has changed it's code, now my answer does not match the new question any more. Nevertheless, hope my answer was useful.

The cause of your problems is that map's operator[] is a mutable operation (if the key doesn't exist, it will be added to the map).
You will have to use the iterator returned from find():
map< lint, vector<lint> >::const_iterator it = inGraph.adjList.find(i);
if (it != inGraph.adjList.end();
for(lint idx = 0; idx < it->size(); idx++ )
os << it->at(idx) << " ";

Related

I can`t solve a passing constant error with my actual knowledge [duplicate]

This question already has an answer here:
std::map access operator deprecated? no operator [] matches these operands
(1 answer)
Closed 8 years ago.
I made a specialization for a bidirectional map when the key type and value type are the same.
Also I made 2 definitions for the operator[] ,one to return constant and one to return non constant. But this did not solve my problem.I get an error that i`m passing constant as *this...
Here it is the specialization:
template<class A>
class BidirectionalMap<A,A>
{
public:
void insert(A a,A b)
{
m1.insert(std::pair<A,A> (a,b));
m1.insert(std::pair<A,A> (b,a));
}
BidirectionalMap& operator =(BidirectionalMap &a)
{
m1=a.m1;
return *this;
}
const A& at(const A& a) const
{
return m1.at(a);
}
int size() const
{
return m1.size();
}
int count(const A& a) const
{
return m1.count(a);
}
A& operator[](const A& a)
{
return m1[a];
}
const A& operator[](const A& a) const
{
return m1[a];////here pinpoints me that error: passing 'const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >' as 'this' argument of 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int; _Tp = int; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]' discards qualifiers [-fpermissive]
}
private:
std::map<A,A> m1;
};
And the error shows in this context:
BidirectionalMap<int, int> f;
f.insert(3, 18);
f.insert(8, 2);
f.insert(7, 5);
f.insert(9, 1);
const BidirectionalMap<int, int> cf = f;
if( f.at(5) == 7 &&
f.count(12) == 0 &&
f.at(8) == 2)
{
yourMark = cf[18] + cf[9];//here is the error
}
Any idea?
operator[] is typically not const in std::map
See http://www.cplusplus.com/reference/map/map/operator%5B%5D/
The reason is that operator[] allows to insert if the element is not present.

error: no match for 'operator[]' in... <near match>

This fail to compile in gcc 4.1.2 / RedHat 5 :
#include <string>
#include <vector>
#include <map>
class Toto {
public:
typedef std::string SegmentName;
};
class Titi {
public:
typedef Toto::SegmentName SegmentName; // import this type in our name space
typedef std::vector<SegmentName> SegmentNameList;
SegmentNameList segmentNames_;
typedef std::map<SegmentName, int> SegmentTypeContainer;
SegmentTypeContainer segmentTypes_;
int getNthSegmentType(unsigned int i) const {
int result = -1;
if(i < segmentNames_.size())
{
SegmentName name = segmentNames_[i];
result = segmentTypes_[ name ];
}
return result;
}
};
The error is :
error: no match for 'operator[]' in '(...)segmentTypes_[name]'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:340:
note: candidates are: _Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](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_string<char, std::char_traits<char>, std::allocator<char> >, int> >]
Why ? The map is rather straightforward. I guess this has to do with the typedefs, but what is wrong ?
[edit] Even if I remove all the typedefs and use std::string everywhere, the problem persists... Am I misusing maps ?
std::map::operator[] is non-const and you're trying to use it from a const method.
You could achieve this using std::map::find, which returns a const_iterator:
SegmentTypeContainer::const_iterator iter = segmentTypes_.find(name);
If you're using C++11, you could also use std::map::at, which will throw an exception if the key is not found in the map:
result = segmentTypes_.at(name);
std::map::operator[] is not a const method, but you are calling it from a const method of your class. The reason for this is that it adds an element if the key is not present.
You can use C++11 at():
result = segmentTypes_.at(name); // throws exception if key not present.
or use std::map::find.
SegmentTypeContainer::const_iterator it = segmentTypes_.find(name);
if (it != segmentTypes_.end())
{
// OK, element with key name is present
result = it->second;
}

Using vector iterators with in a template class

I am attempting to create a vector iterator within a template class I am creating. The following is the trouble code.
void editor<T>::insert()
{
typedef typename std::vector<T>::const_iterator itr;
itr it;
it = this->buffer.begin();
for(int i = 0; i < line_num -1; ++i)
{
++it;
}
this->buffer.insert(it, user_text);
std::cout << "Cool, Your new line has been inserted." << '\n';
}
std::cout << '\n';
}
I am getting the following compile error:
error: no match for ‘operator=’ in ‘it = ((editor<std::basic_string<char> >*)this)->editor<std::basic_string<char> >::buffer.std::vector<_Tp, _Alloc>::begin [with _Tp = std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >, _Alloc = std::allocator<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >*, std::vector<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >, std::allocator<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > > > >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer = std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >*]()’
I have a feeling the compiler is getting confused with my typedef statement above but that is how I have seen to declare the correct iterator, but for some reason it is not working correctly. Any ideas?
If buffer is a std::vector< std::vector<T> > then buffer.begin() is a std::vector< std::vector<T> >::iterator or const_iterator, so your typedef doesn't match.

"No match for operator=" trying to iterate through map in C++

I'm trying to iterate through a map defined as the following:
std::map< size_type, std::pair<size_t, unsigned int> > ridx_;
Now I'm trying to iterate through ridx_ (which is a private member of a class) in the following friend function which overloads operator<<
std::ostream& operator<<(std::ostream &os, const SMatrix &m)
{
std::map< size_type, std::pair<size_t, unsigned int> >::iterator it;
//The following is line 34
for (it = m.ridx_.begin(); it != m.ridx_.end(); it++)
os << it->first << endl;
return os;
}
However g++ errors out with:
SMatrix.cpp:34: error: no match for 'operator=' in 'it =
m->SMatrix::ridx_.std::map<_Key, _Tp, _Compare, _Alloc>::begin with
_Key = unsigned int, _Tp = std::pair,
_Compare = std::less, _Alloc =
std::allocator > >' /usr/include/c++/4.3/bits/stl_tree.h:152: note:
candidates are: std::_Rb_tree_iterator > >&
std::_Rb_tree_iterator > >::operator=(const
std::_Rb_tree_iterator > >&) make: * [myTest] Error 1
What am I doing wrong?
Because m (and therefore m.ridx_) is const, you must use the std::map< size_type, std::pair<size_t, unsigned int> >::const_iterator, not ::iterator here.
If you're using a C++0x compiler, you might want to consider using auto as well:
for (auto it = m.ridx_.begin(); it != m.ridx_.end(); it++)

How can I use a struct as key in a std::map?

I have the following code, but I get an error on on the last line:
struct coord {
int x, y;
bool operator=(const coord &o) {
return x == o.x && y == o.y;
}
bool operator<(const coord &o) {
return x < o.x || (x == o.x && y < o.y);
}
};
map<coord, int> m;
pair<coord, int> p((coord{0,0}),123);
m.insert(p); // ERROR here
How can I use a struct as key in a map?
I tried to change the code to this:
struct coord {
int x, y;
bool const operator==(const coord &o) {
return x == o.x && y == o.y;
}
bool const operator<(const coord &o) {
return x < o.x || (x == o.x && y < o.y);
}
};
But I'm still getting the following error:
C:\Users\tomc\Desktop\g>mingw32-make g++ test.cpp -std=c++0x In file included from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/string:5 0:0,
from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/loc ale_classes.h:42,
from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/ios
_base.h:43,
from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/ios:43,
from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/ostream: 40,
from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/iostream :40,
from test.cpp:1: c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_function.h: In member function 'bool std::less<_Tp>::operator()(const _Tp&, const
_Tp&) const [with _ Tp = coord]': c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_tree.h:1184:4: inst antiated from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare,
_Alloc>::_M_insert_unique(const _Val&) [with _Key
= coord, _Val = std::pair<const coord, int>, _KeyOfValue = std::_Select1st<std:: pair<const coord, int> >, _Compare = std::less<coord>, _Alloc = std::allocator<std::pair<const coord, int>>]' c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_map.h:501:41: insta ntiated from 'std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key,
_Tp> >, _Compare, typename _Alloc::rebind <std::map<_Key, _Tp,
_Compare, _Alloc>::value_type>::other>::iterator, bool> std ::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::map<_Key, _Tp,
_Compare, _ Alloc>::value_type&) [with _Key = coord, _Tp = int,
_Compare = std::less<coord>, _Alloc = std::allocator<std::pair<const coord, int> >, typename std::_Rb_tree<_ Key, std::pair<const _Key,
_Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _ Compare, typename _Alloc::rebind<std::map<_Key, _Tp, _Compare,
_Alloc>::value_ty pe>::other>::iterator = std::_Rb_tree_iterator<std::pair<const coord, int> >, st d::map<_Key,
_Tp, _Compare, _Alloc>::value_type = std::pair<const coord, int>]' test.cpp:56:12: instantiated from here c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_function.h:230:22: er ror: passing 'const coord' as 'this' argument of 'const bool coord::operator<(co nst coord&)' discards qualifiers mingw32-make: *** [game] Error 1
Try and make operator < const:
bool operator<(const coord &o) const {
(Your = operator should probably be == operator and const as well)
By far the simplest is to define a global "less than" operator for your struct in stead of as a member function.
std::map uses - by default - the 'lessthan' functor which, in turn, uses the global "operator<" defined for the key type of the map.
bool operator<(const coord& l, const coord& r) {
return (l.x<r.x || (l.x==r.x && l.y<r.y));
}
As mentioned in the answer by Andrii, you can provide a custom comparison object to the map instead of defining operator< for your struct. Since C++11, you can also use a lambda expression instead of defining a comparison object. Moreover, you don't need to define operator== for your struct to make the map work. As a result, you can keep your struct as short as this:
struct coord {
int x, y;
};
And the rest of your code could be written as follows:
auto comp = [](const coord& c1, const coord& c2){
return c1.x < c2.x || (c1.x == c2.x && c1.y < c2.y);
};
std::map<coord, int, decltype(comp)> m(comp);
Code on Ideone
Another solution, which may be used for third-party data types, is to pass a Comparison object as third template parameter.
example