I am doing school project in university (C ). In nutshell the professor has made a skeleton program that needs functions added to it. The program saves train stations (id, name, coordinates xy) and regions.
I am supposed to make several functions that handle data in the program (add station, count stations, return them in alphabetical order, measure distance between stations, find station with id etc), and most of them I can make myself. But in order to use those functions, I need the first function to work. That function is supposed to create a station object and store it to a vector.
I don't understand why the program gives me an error when I try to build it. I am using qtcreator.
Below is the code I have written:
bool Datastructures::add_station(StationID id, const Name& name, Coord xy)
{
Station x (id, name, xy);
x.id_ = id;
x.name_ = name;
x.coord_ = xy;
if(std::count(stations.begin(), stations.end(), x.id_)){
return false;
}
stations.push_back(x);
return true;
}
The code is referring to the following struct that I created:
struct Station {
StationID id_;
Name name_;
Coord coord_;
Station(StationID id, Name name, Coord coord):
id_(id), name_(name), coord_(coord){
}
};
std::vector<Station> stations;
The initialization of Struct object is nested inside the Datastructures.hh file, under private part of the class Datastructures.
When I try to build the whole program, I receive the error:
/opt/lintula/gcc/include/c /12.1.0/bits/predefined_ops.h:270: error: no match for ‘operator==’ (operand types are ‘Datastructures::Station’ and ‘const std::__cxx11::basic_string<char>’)
In file included from /opt/lintula/gcc/include/c /12.1.0/bits/stl_algobase.h:71,
from /opt/lintula/gcc/include/c /12.1.0/string:50,
from ../prg1/datastructures.hh:10,
from ../prg1/datastructures.cc:7:
/opt/lintula/gcc/include/c /12.1.0/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Iter_equals_val<_Value>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<Datastructures::Station*, std::vector<Datastructures::Station> >; _Value = const std::__cxx11::basic_string<char>]’:
/opt/lintula/gcc/include/c /12.1.0/bits/stl_algobase.h:2123:12: required from ‘typename std::iterator_traits< <template-parameter-1-1> >::difference_type std::__count_if(_InputIterator, _InputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<Datastructures::Station*, vector<Datastructures::Station> >; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const __cxx11::basic_string<char> >; typename iterator_traits< <template-parameter-1-1> >::difference_type = long int]’
/opt/lintula/gcc/include/c /12.1.0/bits/stl_algo.h:4034:29: required from ‘typename std::iterator_traits< <template-parameter-1-1> >::difference_type std::count(_IIter, _IIter, const _Tp&) [with _IIter = __gnu_cxx::__normal_iterator<Datastructures::Station*, vector<Datastructures::Station> >; _Tp = __cxx11::basic_string<char>; typename iterator_traits< <template-parameter-1-1> >::difference_type = long int]’
../prg1/datastructures.cc:80:18: required from here
/opt/lintula/gcc/include/c /12.1.0/bits/predefined_ops.h:270:24: error: no match for ‘operator==’ (operand types are ‘Datastructures::Station’ and ‘const std::__cxx11::basic_string<char>’)
270 | { return *__it == _M_value; }
| ~~~~~~^~~~~~~~~~~
I don't understand what I have done wrong. This is my first post here btw, so sorry for technical mistakes.
CodePudding user response:
std::count(stations.begin(), stations.end(), x.id_))
This is roughly equivalent to the following code:
size_t n=0;
auto b=stations.begin(), e=stations.end();
while (b != e)
{
if (*b == x.id_)
n;
b;
}
The if
statement seems to be end up comparing a Station
with a StationId
, here.
Obviously, your C compiler has no idea what this means. One is a Station
object. The other is a StationID
object, and there is no defined way to compare the two. This is literally comparing an apple to an orange.
There are many different ways to fix this, either by defining an overloaded ==
operator, using a custom comparator, or maybe counting things by hand. It is unclear what your professor expects you to do, based on the information you shared. You should ask your professor for additional guidance, but this is the explanation for the error message from your C compiler.
CodePudding user response:
I would replace your std::count
with std::count_if
if you want to use a particular predicate, otherwise it is expecting x.id_
to be of the same type (or comparable with ==
) to the type Station
if(std::count_if(stations.begin(), stations.end(), [x.id_](const Station& s){ return s.id_ == x.id_; }) > 0)
return false;
}
Although more idiomatically this looks more like a job for std::any_of
if(std::any_of(stations.begin(), stations.end(), [x.id_](const Station& s){ return s.id_ == x.id_; }))
return false;
}