Iterator over a list of pairs in C++? - c++

I defined a list of pairs and wish to access them using an iterator, following an example.
class A{
private:
list<pair<size_type,size_type> > l_edge_;
public:
void function() const{
list<pair<size_type,size_type> >::iterator Iter_;
Iter_ = l_edge_.begin();
}
}
However, I got a compilation error. How can I fix it?
error: no match for 'operator=' (operand types are 'const iterator
{aka const std::_List_iterator<std::pair<unsigned int, unsigned int> >}' and
'std::list<std::pair<unsigned int, unsigned int> >::const_iterator
{aka std::_List_const_iterator<std::pair<unsigned int, unsigned int> >}')

My guess is that you are trying to write a const member function, and not what you copied in the question:
void function() const
{
Iter_ = l_edge_.begin();
}
Now, since the function is const, the l_edge_ member is also const, and so, begin() returns a const_iterator instead of a plain iterator. But that hardly matters because the Iter_ member is also const, so it cannot be assigned to.
Usually you do not want to declare iterators as member variables, unless very special needs. Instead, just declare a local one when you need it, and of the appropriate constness:
class A
{
private:
list<pair<size_type,size_type> > l_edge_;
public:
//const member function
void function() const
{
list< pair<size_type,size_type> >::const_iterator iter = l_edge_.begin();
}
//non-const member function
void function()
{
list< pair<size_type,size_type> >::iterator iter = l_edge_.begin();
}
};

Related

How do I declare an iterator for a map with the following template - std::map<std::string, T> my_map?

I have the following class declaration -
template <typename T>
class Polynomial{
std::map<std::string, T> _polynomial_
}
In a member function I declared an iterator for this -
typename std::map<std::string, T>::iterator it= _polynomial_.begin();
The completed member function looks like this -
template <typename T>
void Polynomial<T>::print(std::ostream& out) const
{
typename std::map<std::string, T>::iterator it= _polynomial_.begin();
std::string term;
while(it != _polynomial_.end()){
term = it->second;
term += it->first;
if(it->first < (T)0){
out << "-" << term;
}
else{
out << "+" << term;
}
term = "";
it++;
}
}
In main, I call the function as follows -
Polynomial <double> p1;
p1.add_term("x0",9.862);
std::cout << p1;
However this does not seem to work and I get errors. GCC complains of a
conversion error -
Polynomial.hpp:32:47: error: conversion from \u2018std::map, double, std::less >, std::allocator, double> > >::const_iterator {aka std::_Rb_tree_const_iterator, double> >}\u2019 to non-scalar type \u2018std::map, double, std::less >, std::allocator, double> > >::iterator {aka std::_Rb_tree_iterator, double> >}\u2019 requested
typename std::map::iterator it= polynomial.begin();
Can someone tell me what is the correct declaration of the iterator?
Polynomial<T>::print is a const member function, inside which the data member _polynomial_ becomes const too, that means what _polynomial_.begin() returns is a const_iterator, which can't be converted to iterator implicitly. (Note that std::map::begin is overloaded with const version and non-const version, the former returns const_iterator and the latter returns iterator.)
Change the code to
typename std::map<std::string, T>::const_iterator it = _polynomial_.begin();
// ^^^^^^
or use auto instead, it would deduce the correct type for you.
auto it = _polynomial_.begin();

how can to use array containing c++ map

I have difficulty understanding this part of a code? Is it possible to get pictorial/diagram explanation.
//test.h
typedef std::map<std::string, std::string> mType;
static const m_Type::value_type data[] = {
m_Type::value_type("A", "B"),
m_Type::value_type("C", "D"),
m_Type::value_type("E", "F")
};
//test.cc
void test(std::map<std::string, std::string>::value_type data)
{
cout<<data[0].first<<endl;
}
//main.cc
test(data);
In main.cc I wanted to call test() to print elements but getting error
main.cc: In function 'void test(std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >)':
main.cc:10: error: no match for 'operator[]' in 'data[0]'
You have to declare the function the following way
void test( const std::map<std::string, std::string>::value_type data[] )
{
cout<<data[0].first<<endl;
}
because originally data is defined as an array that you are going to pass to the function. Otherwise you may not use the subscript operator.
Also you need to use qualifier const for the parameter because array data also is defined as a constant array.
As for this type
m_Type::value_type
then it is equivalent to std::pair<const std::string, std::string> So this declaration
static const m_Type::value_type data[] = { /*...*/ };
is equivalent to
static const std::pair<const std::string, std::string> data[] = { /*...*/ };
You are supposed to pass to test a value_type not the whole map.
A value_type corresponds to a pair(key, value) and is define like so in stdlib : typedef pair<const Key, Type> value_type;
therefore this data[0]makes no sense. Should be data.first

error in type conversion in operator overloading

I have a template class and I need to overload operator ==. I do this in the following way
template <typename T>
class Polynomial {
vector<T> coefficients;
public:
Polynomial(vector<T> c);
bool operator ==(const Polynomial& second) const {
const typename vector<T>::iterator thisBegin = this->coefficients.begin();
const typename vector<T>::iterator secondBegin = second.coefficients.begin();
for ( ; ((thisBegin != this->coefficients.end()) &&
(secondBegin != second.coefficients.end()));
++thisBegin, ++secondBegin) {
if (*thisBegin != *secondBegin)
return false;
}
while (thisBegin != this->coefficients.end()) {
if (*thisBegin != 0)
return false;
++thisBegin;
}
while (secondBegin != second.coefficients.end()) {
if (*secondBegin != 0)
return false;
++secondBegin;
}
return true;
}
};
However, when I create two objects of this class with T=int and try to apply this operator
Polynomial<int> first(firstVector);
Polynomial<int> second(secondVector);
std::cout << (first == second) << std::endl;
I got the error
problem2.cpp: In instantiation of ‘bool Polynomial<T>::operator==(const Polynomial<T>&) const [with T = int; Polynomial<T> = Polynomial<int>]’:
problem2.cpp:63:32: required from here
problem2.cpp:23:83: error: conversion from ‘std::vector<int, std::allocator<int> >::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >}’ to non-scalar type ‘std::vector<int, std::allocator<int> >::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >}’ requested
Can someone point out what's wrong with this conversion? Thanks!
You are trying to convert a const_iterator to an iterator:
const typename vector<T>::iterator thisBegin = this->coefficients.begin();
this is const in this context, so this->coefficients.begin(); returns a const_iterator. Try this:
typename vector<T>::const_iterator thisBegin = this->coefficients.begin();
Note also that thisBegin is not const, as in your example. This is because you then do this kind of thing:
++secondBegin;
which requires the const_iterator to be non-const (meaning you can modify the iterator, but not the thing it points to).
your method is const that mean that you can only call const functions on this and
you passing const reference to method, so you can only call const functions on it
So, both
this->coefficients.begin();
second.coefficients.begin()
returns const iterators.
You cannot assign them to non-const ones.
There is a solution:
vector<T>::const_iterator& thisBegin = this->coefficients.begin();
vector<T>::const_iterator& secondBegin = second.coefficients.begin();
(use references to const_iterator)
Even better:
auto& thisBegin = this->coefficients.begin();
auto& secondBegin = second.coefficients.begin();
(use references to auto, C++11 feature)
BTW, you can simply compare two vectors using std::mismatch

Sorting deque of boost tuples

Not sure if I have a simple typo somewhere, but I'm running into issues in sorting a deque of tuples.
So, my deque looks like this:
std::deque<boost::tuple<unsigned int, unsigned int> > messages;
And then I have my call to sort:
sort(messages.begin(), messages.end(), msg_sort_criteria);
And my sorting function:
bool msg_sort_criteria(boost::tuple<unsigned int, unsigned int> lhs, boost::tuple<unsigned int, unsigned int> rhs)
{
return boost::get<1>(lhs) < boost::get<1>(rhs);
}
What happens is that I get errors in stl_heap.h and stl_algo.h.
For instance,
Called object type '<bound member function type>' is not a function or
function parameter.
Edit:
For clarification, this is all taking place within private members of a class.
class Messages::MessageImpl{
private:
std::deque<boost::tuple<unsigned int, unsigned int> > messages;
bool msg_sort_criteria(boost::tuple<unsigned int, unsigned int> lhs, boost::tuple<unsigned int, unsigned int> rhs)
{
return boost::get<1>(lhs) < boost::get<1>(rhs);
}
void fn()
{
sort(msg_queue_.begin(), msg_queue_.end(), msg_sort_criteria);
}
}
Mostly reposting from comment.
Change your implementation to:
class Messages::MessageImpl{
private:
std::deque<boost::tuple<unsigned int, unsigned int> > messages;
static bool msg_sort_criteria(boost::tuple<unsigned int, unsigned int> lhs,
boost::tuple<unsigned int, unsigned int> rhs)
{
return boost::get<1>(lhs) < boost::get<1>(rhs);
}
void fn()
{
sort(msg_queue_.begin(), msg_queue_.end(), &MessageImpl::msg_sort_criteria);
}
};

find() problems

I've got an error while using find() function. Here is the code:
#include <iostream>
#include <map>
#define N 100000
using namespace std;
int main (int argc, char * const argv[]) {
map<int,int> m;
for (int i=0; i<N; i++) m[i]=i;
find(m.begin(), m.end(), 5);
return 0;
}
I'm getting an compiller error:
error: no match for 'operator==' in '__first. __gnu_debug::_Safe_iterator<_Iterator, _Sequence>::operator* [with _Iterator = std::_Rb_tree_iterator<std::pair<const int, int> >, _Sequence = __gnu_debug_def::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >]() == __val'
Including 'algorithm' nothing changes. Compiling in VS2008 shows similar error.
I know about m.find(), but I realy need to use find() too.
Thanks a lot for your assistance!
P.S. Actualy, the task is to compare speed of m.find(5) and find(m.begin(), m.end(), 5), so I need to make both of them work properly.
begin() and end() on all STL containers provide access to elements of those collections. Type of those elements is known as value_type of the container. For std::map<Key, Value>, its value_type is std::pair<Key, Value>. Therefore, your find function is trying to find a pair<int, int> which is equal to 5. Since there's no operator== defined to compare pair<int, int> and int, you get the error.
The correct way to do this (so long as you want to avoid member find()) is to use std::find_if:
template <class First>
struct first_equal
{
const First value;
first_equal(const First& value)
: value(value)
{
}
template <class Second>
bool operator() (const std::pair<First, Second>& pair) const
{
return pair.first == value;
}
};
...
find_if(m.begin(), m.end(), first_equal<int>(5));
You could also overload operator== for pair and int to do what you want, but it's a very hackish way (because it will affect all your code, and because such a comparison has no meaning in general).
find() requires a parameter that can be compared to *iterator. For your map, this will be pair<int,int>. You'll need to create a dummy pair, plus a comparison functor to compare the pairs.
Just use m.find(5)