using find_if in set - c++

In my main.cpp:
using namespace std;
#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
#include <cstring>
#include <sstream>
#include <algorithm>
class findme
{
public:
bool operator()(const std::string& s) {
return s == "tom";
}
};
int main(int argc, char *argv[])
{
set<string> myset;
myset.insert("tom");
myset.insert("jerry");
cout << myset.size();
set<string>::iterator it;
if (find_if(myset.begin(), myset.end(), findme())) {
cout << "found tom \n";
}
return EXIT_SUCCESS;
}
when I compiled the program, it got an error:
Could not convert std::find_if [with _InputIterator = std::_Rb_tree_const_iterator<std::string>, _Predicate = findme]((&myset)->std::set<_Key, _Compare, _Alloc>::begin [with _Key = std::string, _Compare = std::less<std::string>, _Alloc = std::allocator<std::string>](), (&myset)->std::set<_Key, _Compare, _Alloc>::end [with _Key = std::string, _Compare = std::less<std::string>, _Alloc = std::allocator<std::string>](), (findme(), findme()))' to 'bool'
Can anyboy tell me where were I wrong? thank you

std::find_if returns an iterator to the found element (or one-past-the-end if no element matched the predicate):
std::set<std::string>::iterator it =
std::find_if(myset.begin(), myset.end(), findme());
if (it != myset.end())
{
// etc.

Related

Getting build error when trying to implement a comparator for sorting map data type?

I am trying to build a comparator for a map to be used with sort() function.
consider a map object called right with an id and coordinates as the basic member. I am trying to sort the elements of this object with euclidean distance. below is the code.
#include <iostream>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>
namespace NONBCG_DATA_ALGO
{
template<typename T>
T distance(std::vector<T> P1, std::vector<T> P2 , int dim)
{
if ((typeid(T) == typeid(int)) || (typeid(T) == typeid(double)) || (typeid(T) == typeid(float)) )
{
float accum = 0;
for(int i=0; i<dim; i++)
{
accum += pow((P2[i]-P1[i]),2);
}
return sqrt(accum);
}
else
{
throw std::invalid_argument("Type should be either int,double or float");
}
}
template<typename T>
class distance_compare_asc_comp_id_2D
{
public:
distance_compare_asc_comp_id_2D(std::vector<T> ipt):Pt(ipt){};
bool operator()(const std::pair<int,std::vector<T>>& p1,const std::pair<int,std::vector<T>>&p2)
{
if ((typeid(T) == typeid(int)) || (typeid(T) == typeid(double)) || (typeid(T) == typeid(float)) )
{
return NONBCG_DATA_ALGO::distance<T>(Pt,p1.second,2) < NONBCG_DATA_ALGO::distance(Pt,p2.second,2);
}
else
{
throw std::invalid_argument("Type should be either int,double or float");
}
}
private:
std::vector<T> Pt;
};
};
int main() {
// Write C++ code here
std::map<int,std::vector<double>> right;
right.insert(std::pair<int,std::vector<double>>(1,{2,8,3}));
right.insert(std::pair<int,std::vector<double>>(6,{2.5,5.4,3}));
sort(right.begin(),right.end(),NONBCG_DATA_ALGO::distance_compare_asc_comp_id_2D<double>(std::vector<double>{0.0,0.0}));
return 0;
}
I get the following error while building
In file included from /usr/include/c++/9/algorithm:62,
from /tmp/wxeRdlKRUn.cpp:6:
/usr/include/c++/9/bits/stl_algo.h: In instantiation of 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<NONBCG_DATA_ALGO::distance_compare_asc_comp_id_2D<double> >]':
/usr/include/c++/9/bits/stl_algo.h:4899:18: required from 'void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >; _Compare = NONBCG_DATA_ALGO::distance_compare_asc_comp_id_2D<double>]'
/tmp/wxeRdlKRUn.cpp:70:122: required from here
/usr/include/c++/9/bits/stl_algo.h:1968:22: error: no match for 'operator-' (operand types are 'std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >' and 'std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >')
1968 | std::__lg(__last - __first) * 2,
| ~~~~~~~^~~~~~~~~
I really appreciate any help you can provide.
molbdnilo's suggestion of using a vector of pairs fits perfectly for my usage. Thanks, everyone for the help!

error: assignment of read-only location ‘* __result’

On compilation of the given code, I get the following error messages:
/usr/include/c++/9.2.0/bits/stl_algo.h: In instantiation of ‘_OutputIterator
std::__merge(_InputIterator1, _InputIterator1, _InputIterator2, _InputIterator2, _OutputIterator,
_Compare) [with _InputIterator1 = __gnu_cxx::__normal_iterator<std::pair<int, int>*,
std::vector<std::pair<int, int> > >; _InputIterator2 = __gnu_cxx::__normal_iterator<std::pair<int,
int>*, std::vector<std::pair<int, int> > >; _OutputIterator = bool (*)(std::pair<int, int>,
std::pair<int, int>); _Compare = __gnu_cxx::__ops::_Iter_less_iter]’:
/usr/include/c++/9.2.0/bits/stl_algo.h:4929:37: required from ‘_OIter std::merge(_IIter1, _IIter1,
_IIter2, _IIter2, _OIter) [with _IIter1 = __gnu_cxx::__normal_iterator<std::pair<int, int>*,
std::vector<std::pair<int, int> > >; _IIter2 = __gnu_cxx::__normal_iterator<std::pair<int, int>*,
std::vector<std::pair<int, int> > >; _OIter = bool (*)(std::pair<int, int>, std::pair<int, int>)]’
jdoodle.cpp:61:81: required from here
/usr/include/c++/9.2.0/bits/stl_algo.h:4874:18: error: assignment of read-only location ‘* __result’
4874 | *__result = *__first2;
| ~~~~~~~~~~^~~~~~~~~~~
/usr/include/c++/9.2.0/bits/stl_algo.h:4879:18: error: assignment of read-only location ‘* __result’
4879 | *__result = *__first1;
| ~~~~~~~~~~^~~~~~~~~~~
Following is the code:
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <utility>
#include <cfloat>
using namespace std;
struct Node
{
int left;
int right;
double dist;
};
bool x_sort(pair<int,int> x,pair<int,int> y)
{
if(x.first<y.first)
return true;
return false;
}
bool y_sort(pair<int,int> x,pair<int,int> y)
{
if(x.second<y.second)
return true;
return false;
}
Node closest_dist(vector<pair<int,int>> arr,int low,int high)
{
Node x;
double min_dist=DBL_MAX;
if(high-low+1<=3)
{
for(int i=low;i<=high;i++)
{
for(int j=i+1;j<=high;j++)
{
double dist=sqrt(pow((arr[i].first-arr[j].first),2)+pow((arr[i].second-arr[j].second),2));
if(dist<min_dist)
{
min_dist=dist;
x.left=i;
x.right=j;
x.dist=min_dist;
}
}
}
}
int mid=low+(high-low)/2;
Node x1=closest_dist(arr,low,mid);
Node x2=closest_dist(arr,mid+1,high);
double min_dist_now=min(x1.dist,x2.dist);
merge(arr.begin()+low,arr.begin()+mid,arr.begin()+mid+1,arr.begin()+high,y_sort); //line which gives the error(most probably)
vector<pair<int,int>> strip;
for(int i=low;i<=high;i++)
if((abs(arr[mid].first-arr[i].first)<min_dist_now))
strip.push_back(arr[i]);
for(int i=0;i<strip.size()-7;i++)
{
for(int j=i+1;j<=i+7&&j<strip.size();j++)
{
double dist=sqrt(pow((arr[i].first-arr[j].first),2)+pow((arr[i].second-arr[j].second),2));
if(dist<min_dist_now)
{
min_dist_now=min_dist;
x.left=i;
x.right=j;
x.dist=min_dist;
}
}
}
return x;
}
int main()
{
int n;
cin>>n;
vector<pair<int,int>> arr;
for(int i=0;i<n;i++)
{
int x,y;
cin>>x>>y;
arr.push_back(make_pair(x,y));
}
sort(arr.begin(),arr.end(),x_sort);
for(int i=0;i<n;i++)
{
cout<<arr[i].first<<" "<<arr[i].second;
cout<<"\n";
}
Node ans=closest_dist(arr,0,n-1);
cout<<ans.left<<" "<<ans.right<<" "<<ans.dist<<"\n";
return 0;
}
I have written the code as a solution to the problem https://www.spoj.com/problems/CLOPPAIR/
I am new to STL and on finding a solution to the same error, most implementations have misused the keyword 'const' that has lead to this error. However, in my case there is no usage of 'const'. Can someone please help me out on this?
Seems you mistook what the fifth parameter for std::merge is for.
That parameter should be an iterator which tells the compiler where to place the merged data. You've supplied a function however.
It looks like you are trying to supply a custom sort criteria, but that would be the sixth parameter to std::merge.
https://en.cppreference.com/w/cpp/algorithm/merge

Permutations of a string --error: no matching function for call to ‘std::set<char>::insert(std::string&)’

I am not a professional c++ programmer. I have tried to write a program to display all possible permutations of a given input string assuming if the string contains duplicate characters. This the code I have written so far:
Latest update of my code (permutation.cpp):
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <list>
#include <set>
#include <iterator>
#include <sstream>
#include <cstdlib>
using namespace std;
//factorial function
int factorial(int n){
if (n==0) return 1;
else{
return n*factorial(n-1);
}
}
int main (int argc, char *argv[]) {
srand ( time(NULL) ); //initialize the random seed
char* text;
std::set<char> mySwapList;
if ( argc < 1 )
{
cout << endl << "Please write a word in the following of the command line" << endl << endl;
return 1;
}
else if ( argc != 2 ) // argc should be 2 for correct execution
{ // We print argv[0] assuming it is the program name
strcpy (text,argv[1]);
cout<<endl<<"usage: "<< argv[0] <<" to compute all the permutations \n"<<endl;
return 1;
}
int ss=sizeof(text);
int length = ss;
int k=0;
cout << "length of the word:"<<endl<< length<<endl;
int total=factorial(length);
while (k< total)
{
char arr[ss];
int index=0;
stringstream ssin(text);
while (ssin.good() && index<ss){
ssin>>arr[index];
++index;
}
std::list<char> word(arr, arr+ss);
std::list<char> mylist;
unsigned int j=0;
while (j < length)
{
int n=word.size();
int RandIndex = rand() % n;
std::list<char>::iterator vi= word.begin();
std::advance(vi,RandIndex);
std::list<char>::iterator iter= mylist.begin();
mylist.insert(iter,*vi);
word.remove(*vi);
j++;
}
char str[ss];
int ii=0;
for (std::list<char>::iterator ix=mylist.begin(); ix!=mylist.end(); ++ix)
{
str[ii]=*ix;
ii++;
}
string newWord = string(str);
for (std::set<char>::iterator iss=mySwapList.begin(); iss!=mySwapList.end(); ++iss)
{
string w(1,*iss);
if (newWord != w)
{
mySwapList.insert(newWord);
k++;
}
}
}
//Loop for printing the list
for(std::set<char>::iterator it = mySwapList.begin(); it != mySwapList.end(); ++it)
cout << *it << " ";
cout << endl;
return 0;
}
I get a a good deal of error messages when I compile the code, including:
Updated errors:
permutation.cpp: In function ‘int main(int, char**)’:
permutation.cpp:82:39: error: no matching function for call to ‘std::set<char>::insert(std::string&)’
mySwapList.insert(newWord);
^
permutation.cpp:82:39: note: candidates are:
In file included from /usr/include/c++/4.8/set:61:0,
from permutation.cpp:9:
/usr/include/c++/4.8/bits/stl_set.h:460:7: note: std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = char; _Compare = std::less<char>; _Alloc = std::allocator<char>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<char>; std::set<_Key, _Compare, _Alloc>::value_type = char]
insert(const value_type& __x)
^
/usr/include/c++/4.8/bits/stl_set.h:460:7: note: no known conversion for argument 1 from ‘std::string {aka std::basic_string<char>}’ to ‘const value_type& {aka const char&}’
/usr/include/c++/4.8/bits/stl_set.h:497:7: note: std::set<_Key, _Compare, _Alloc>::iterator std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = char; _Compare = std::less<char>; _Alloc = std::allocator<char>; std::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<char>; std::set<_Key, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<char>; std::set<_Key, _Compare, _Alloc>::value_type = char]
insert(const_iterator __position, const value_type& __x)
^
/usr/include/c++/4.8/bits/stl_set.h:497:7: note: candidate expects 2 arguments, 1 provided
/usr/include/c++/4.8/bits/stl_set.h:517:2: note: template<class _InputIterator> void std::set<_Key, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = char; _Compare = std::less<char>; _Alloc = std::allocator<char>]
insert(_InputIterator __first, _InputIterator __last)
^
/usr/include/c++/4.8/bits/stl_set.h:517:2: note: template argument deduction/substitution failed:
permutation.cpp:82:39: note: candidate expects 2 arguments, 1 provided
mySwapList.insert(newWord);
I can not figure out why I got the above errors. Any suggestion?
Based on the question title you want to convert string to list.
You can't do it directly but you can use string iterator:
#include <string>
#include <list>
int main(int argc, _TCHAR* argv[])
{
std::string strTest = "hello!";
std::list<char> list(strTest.begin(), strTest.end());
return 0;
}
Edit: But based on your code you don't need list at all. You can use std::string everywhere. It has insert and [] stuff. It is almost the same as vector<char> but with additional functionality.
You used undefined class members.
Try strcpy_s() to char* arrays.
Using vector as a container for strings at the end of the code for mySwapList solves the problem of accepting strings as well as being easy to access each component of the vector. Here is the debugged and working version of the original question:
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <list>
#include <set>
#include <iterator>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
using std::vector;
//factorial function
int factorial(int n){
if (n==0) return 1;
else{
return n*factorial(n-1);
}
}
int main () {
srand ( time(NULL) ); //initialize the random seed
std::string text;
vector<std::string> mySwapList;
std::ostream_iterator<char> output(cout," ");
cout << endl << "Please write a word in the following of the command line" << endl << endl;
cin >>text;
int ss=text.size();
int k=0;
cout << "length of the word:" << endl << ss<<endl<<"input value:\n" <<text<< endl;
int total=factorial(ss);
cout << "The number of final permutations :\n"<<total<<endl;
while (k< total)
{
char arr[ss];
int index=0;
stringstream ssin(text);
while (ssin.good() && index<ss){
ssin>>arr[index];
++index;
}
std::list<char> word;
//insert items from arr into word list
word.insert(word.begin(),arr, arr+ss);
//A tool to print lists
cout<<"word contains:\n "<<endl;
std::copy(word.begin(),word.end(),output);
cout << endl;
std::list<char> mylist;
unsigned int j=0;
while (j < ss)
{
int n=word.size();
int RandIndex = rand() % n;
std::list<char>::iterator vi= word.begin();
std::advance(vi,RandIndex);
word.erase(vi);
std::list<char>::iterator iter= mylist.begin();
mylist.insert(iter,*vi);
j++;
}
cout << "constructed permuted word:"<<endl;
std::copy(mylist.begin(),mylist.end(),output);
cout << endl;
char str[ss];
str[ss]='\0';
int ii=0;
for (std::list<char>::iterator ix=mylist.begin(); ix!=mylist.end(); ++ix)
{
str[ii]=*ix;
ii++;
}
string newWord = string(str);
cout << "New Word :"<< endl << newWord <<" size of string:\n"<< (sizeof(str)/sizeof(*str)) << endl;
if (k==0)
{
mySwapList.push_back(newWord);
k++;
}
else
{
int flag=0;
for (int i=0;i<mySwapList.size();i++)
{
if (mySwapList[i]==newWord)
flag=1;
}
if (flag!=1)
{
mySwapList.push_back(newWord);
k++;
}
}
}
//Loop for printing the vector mySwapList
for(unsigned int i=0; i<mySwapList.size();i++)
cout << mySwapList[i] << " ";
cout << endl;
return 0;
}

Compiling error when insert pair into set [duplicate]

This question already has answers here:
problems with c++ set container
(2 answers)
Closed 6 years ago.
I can't understand why g++ returns error like this:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_pair.h: In function 鈥榖ool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) [with _T1 = int, _T2 = stop]鈥
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227: instantiated from 鈥榖ool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = std::pair<int, stop>]鈥
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:921: instantiated from 鈥榮td::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique(const _Val&) [with _Key = std::pair<int, stop>, _Val = std::pair<int, stop>, _KeyOfValue = std::_Identity<std::pair<int, stop> >, _Compare = std::less<std::pair<int, stop> >, _Alloc = std::allocator<std::pair<int, stop> >]鈥
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_set.h:321: instantiated from 鈥榮td::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = std::pair<int, stop>, _Compare = std::less<std::pair<int, stop> >, _Alloc = std::allocator<std::pair<int, stop> >]鈥
newGraph.cpp:48: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_pair.h:104: error: no match for 鈥榦perator<鈥in 鈥榑_x->std::pair<int, stop>::second < __y->std::pair<int, stop>::second鈥
Here is my code:
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <set>
#include <utility> // for pair
#include <algorithm>
#include <iterator>
const int max_weight = INT_MAX;
struct stop {
std::string name_stop;
int id_stop;
bool operator !=(const stop &rhs) const
{
return ((id_stop != rhs.id_stop) || (name_stop != rhs.name_stop));
}
};
struct neighbor {
stop target;
int weight;
neighbor(stop arg_target, int arg_weight) : target(arg_target), weight(arg_weight) { }
};
std::list<stop> dijkstraComputeAndGetShortestPaths(stop src,
stop dst,
std::vector< std::vector<neighbor> > &adj_list,
std::vector<int> &min_distance,
std::vector<stop> &previous)
{
stop fake_stop;
fake_stop.id_stop = INT_MAX;
fake_stop.name_stop = "Null";
std::list<stop> path;
int n = adj_list.size();
min_distance.clear();
min_distance.resize(n, max_weight);
min_distance[src.id_stop] = 0;
previous.clear();
previous.resize(n, fake_stop);
std::set< std::pair< int, stop > > vertex_queue;
vertex_queue.insert(std::make_pair(min_distance[src.id_stop], src));
while (!vertex_queue.empty())
{
int dist = vertex_queue.begin()->first;
stop u = vertex_queue.begin()->second;
vertex_queue.erase(vertex_queue.begin());
// Visit each edge exiting u
const std::vector<neighbor> &neighbors = adj_list[u.id_stop];
for(std::vector<neighbor>::const_iterator neighbor_iter = neighbors.begin();
neighbor_iter != neighbors.end();
neighbor_iter++)
{
stop v = neighbor_iter->target;
int weight = neighbor_iter->weight;
int distance_through_u = dist + weight;
if (distance_through_u < min_distance[v.id_stop]) {
vertex_queue.erase(std::make_pair(min_distance[v.id_stop], v));
min_distance[v.id_stop] = distance_through_u;
previous[v.id_stop] = u;
vertex_queue.insert(std::make_pair(min_distance[v.id_stop], v));
}
}
if(u.id_stop == dst.id_stop)
{
std::cout << "Find : ";
for ( ; dst != fake_stop; dst = previous[dst.id_stop])
{
path.push_front(dst);
}
return path;
}
}
}
int main()
{
std::vector< std::vector<neighbor> > adj_list(9);
stop stop_s;
stop_s.id_stop = 1001;
stop_s.name_stop = "A";
stop stop_x;
stop_x.id_stop = 1002;
stop_x.name_stop = "B";
adj_list[stop_s.id_stop].push_back(neighbor(stop_x, 5));
stop_s.id_stop = 1003;
stop_s.name_stop = "C";
adj_list[stop_x.id_stop].push_back(neighbor(stop_s, 15));
stop_x.id_stop = 1004;
stop_x.name_stop = "D";
adj_list[stop_s.id_stop].push_back(neighbor(stop_x, 20));
stop_s.id_stop = 1001;
stop_s.name_stop = "A";
std::vector<int> min_distance;
std::vector<stop> previous;
std::list<stop> path = dijkstraComputeAndGetShortestPaths(stop_s, stop_x, adj_list, min_distance, previous);
std::cout << "Distance from 1001 to 1004: " << min_distance[stop_x.id_stop] << std::endl;
//std::cout << "Path : ";
#if 0
for (int index = 0; index < path.size(); index++)
{
auto path_front = path.begin();
std::advance(path_front, index);
std::cout << path_front->id_stop << " ";
}
std::cout << std::endl;
#endif
return 0;
}
std::set require you to specify an operator < for the type it holds or you can supply your own comparison functor as a template parameter. Since stop does not have an operator < the operator < from std::pair is not compileable since it relies on using the operator < of the types it holds.. You either need to supply your own comparison functor or define an operator < for stop.

Implementing BFS using C++

I am trying to implement BFS in C++, Here is the code.
#include <iostream>
#include <list>
#include <string>
#include <limits>
#include <map>
int infinity=std::numeric_limits<int>::max();
struct Node{
int value;
int distance;
std::string color;
Node(int val):
value(val),
distance(infinity),
color("white")
{}
};
//using AdjList = std::map<Node*,std::list<Node*>>;
typedef std::map<Node*,std::list<Node*>> AdjList;
AdjList create_graph()
{
Node* n1 = new Node(1);
Node* n2 = new Node(2);
Node* n3 = new Node(3);
Node* n4 = new Node(4);
Node* n5 = new Node(5);
Node* n6 = new Node(6);
Node* n7 = new Node(7);
Node* n8 = new Node(8);
AdjList m;
m[n1] = {n2, n5};
m[n2] = {n1, n6};
m[n3] = {n4, n6, n7};
m[n4] = {n3, n7, n8};
m[n5] = {n1};
m[n6] = {n2, n3, n7};
m[n7] = {n3, n4, n6, n8};
m[n8] = {n4, n7};
return m;
}
void bfs(const AdjList& m, Node* n1)
{
std::list<Node*> queue;
queue.push_back(n1);
unsigned count = 0;
while (!queue.empty())
{
auto n = queue.front();
std::cout << n->value << std::endl;
queue.pop_front();
std::cout << *(m[n].begin()) << std::endl;
for(auto it = m[n].begin(); it != m[n].end(); ++it)
{
if ((*it)->color != "black")
queue.push_back(*it);
}
n->color = "black";
n->distance = count;
++count;
}
}
On trying to compile with gcc, I receive the following error messages.
bfs.cpp: In function ‘void bfs(const AdjList&, Node*)’:
bfs.cpp:59:27: error: passing ‘const AdjList {aka const std::map<Node*, std::list<Node*> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = Node*; _Tp = std::list<Node*>; _Compare = std::less<Node*>; _Alloc = std::allocator<std::pair<Node* const, std::list<Node*> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::list<Node*>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = Node*]’ discards qualifiers [-fpermissive]
std::cout << *(m[n].begin()) << std::endl;
^
bfs.cpp:60:20: error: passing ‘const AdjList {aka const std::map<Node*, std::list<Node*> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = Node*; _Tp = std::list<Node*>; _Compare = std::less<Node*>; _Alloc = std::allocator<std::pair<Node* const, std::list<Node*> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::list<Node*>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = Node*]’ discards qualifiers [-fpermissive]
for(auto it = m[n].begin(); it != m[n].end(); ++it)
^
bfs.cpp:60:40: error: passing ‘const AdjList {aka const std::map<Node*, std::list<Node*> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = Node*; _Tp = std::list<Node*>; _Compare = std::less<Node*>; _Alloc = std::allocator<std::pair<Node* const, std::list<Node*> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::list<Node*>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = Node*]’ discards qualifiers [-fpermissive]
for(auto it = m[n].begin(); it != m[n].end(); ++it)
I am not sure what is wrong. Please point out the mistake.
std::map::operator[] is non-const because it will insert elements if needed:
int main()
{
std::map<std::string, std::string> m;
m["new element"] = "1";
}
The problem is that m is a const AdjList&, on which you cannot call non-const member functions. You can use std::map::find() instead:
auto itor = m.find(n);
if (itor != m.end())
std::cout << *(m->second.begin()) << std::endl;
Two C++11 features will make your life much easier
the at() const function for maps, which is like [] but throws an out of range exception if the key is not there, instead of adding a new item to the map.
the for loop over containers
So :
for (auto it : m.at(n)) {
if (it->color != "black")
queue.push_back(it);
}