Sorting vector of Pointers of Custom Class - c++

I have vector<FPGA*> current_generation_, which I'd like to sort by FPGA member fitness_ using the sort_members function. Applicable code follows:
bool sort_members (FPGA* fpga_first, FPGA* fpga_second) {
return (fpga_first->fitness() < fpga_second->fitness());
};
fpga.hpp
#include <vector>
class FPGA {
public:
explicit FPGA(int input_gates, int output_gates, int normal_gates);
const int fitness();
protected:
int fitness_;
};
fpga.cpp
FPGA::FPGA() {
this->fitness_ = 0;
}
const int FPGA::fitness() {
return this->fitness_;
}
implementation:
std::sort(this->current_generation_.begin(), this->current_generation_.end(), sort_members);
errors:
/usr/include/c++/4.9/bits/stl_algo.h: In instantiation of ‘void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(FPGA*, FPGA*)>]’:
/usr/include/c++/4.9/bits/stl_algo.h:4717:78: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>; _Compare = bool (*)(FPGA*, FPGA*)]’
/usr/include/c++/4.9/bits/stl_algo.h:1968:22: error: no match for ‘operator-’ (operand types are ‘std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>’ and ‘std::__detail::_Node_iterator<std::pair<const int, FPGA*>, false, false>’)
std::__lg(__last - __first) * 2,
The remainder of the total error string is huge, but I believe is mostly what the compiler believes(falsely) are candidates. I'm not extremely familiar with c++, and a compiler error of this magnitude and complexity is confusing to me.
I can provide more context if needed. Thanks!
EDIT: A dash.
EDIT EDIT: I screwed up, and was trying to sort the wrong member. Hooray.

The only error that I see is this>current_generation_.end() instead that ->.
In addition you should consider declaring your compare fuction as accepting two const FPGA* instead that just FPGA*. This will force you to declare fitness() as const int fitness() const but it makes sense to have it const.
Mind that since you are using C++11 you can directly use a lambda:
std::sort(data.begin(), data.end(), [](const FPGA* f1, const FPGA* f2) { ... });
You also have the choice to overload operator< directly:
class FPGA {
...
bool operator<(const FPGA* other) const { return fitness_ < other->fitness_; }
}
std::sort(data.begin(), data.end());
This could be useful if it doesn't make sense to have other criteria to compare two FPGA instances since you add some semantics to the object itself.

Related

How can I create struct object from funtion parameters?

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.
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.
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;
}

Why is my variable constant when it wasn't when I defined it?

Currently, I have a problem when trying to find a variable within a vector.
I defined a vector, tests, set to contain my own structure Test. It contains two variables, one and two. Both are instances of Test.
Test isn't much, it only contains an int and char.
I defined a macro that finds wether or not an instance of an object is in a given vector or not.
When I attempt to compile my code, it results in this error:
In file included from /usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/bits/stl_algobase.h:71,
from /usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/bits/char_traits.h:39,
from /usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/ios:40,
from /usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/ostream:38,
from /usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/iostream:39,
from test.cpp:1:
/usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_equals_val<_Value>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<Test*, std::vector<Test> >; _Value = const Test]':
/usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/bits/stl_algobase.h:1932:14: required from '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Test*, std::vector<Test> >; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const Test>]'
/usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/bits/stl_algobase.h:1977:23: required from '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator<Test*, std::vector<Test> >; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const Test>]'
/usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/bits/stl_algo.h:3902:28: required from '_IIter std::find(_IIter, _IIter, const _Tp&) [with _IIter = __gnu_cxx::__normal_iterator<Test*, std::vector<Test> >; _Tp = Test]'
test.cpp:19:6: required from here
/usr/local/Cellar/gcc/10.2.0/include/c++/10.2.0/bits/predefined_ops.h:268:17: error: no match for 'operator==' (operand types are 'Test' and 'const Test')
268 | { return *__it == _M_value; }
|
What I find interesting is that the variable I am checking is considered constant, even though when I defined it, it wasn't.
Source code:
#include <iostream>
#include <vector>
#include <algorithm>
#define isin(one, two) (std::find(one.begin(), one.end(), two) != one.end())
struct Test {
int one;
char two;
};
int main() {
Test one = { 6, 'n' };
Test two = { 9, 'r' };
std::vector<Test> tests = { one, two };
if (isin(tests, one)) {
std::cout << "one is in tests\n";
} else {
std::cout << "one is not in tests\n";
}
return 0;
}
Why is one considered constant? Did I accidentally do something wrong?
error: no match for 'operator==' (operand types are 'Test' and 'const Test')
You don't have an equality operator defined for Test. You need to define operator== so it can know how to check if two instances are equal.
The error message is telling you that there is no operator== defined that can compare a non-const Test object on the left to a const Test object on the right. The compiler does not generate a default operator== for you (though, this is actually addressed in C++20, though it is not automatic, you still have to request it explicitly).
The 2nd Test in the error message is const because that is how std::find() is taking it in:
template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value )
std::find() iterates the specified range comparing value to each element in the range using operator==, similar to this:
template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value )
{
while (first != last) {
if (*first == value) { // <-- here
return first;
}
++first;
}
return last;
}
In this case, T is Test, so value is const Test &value. tests is a non-const std::vector<Test>, so its iterators refer to non-const Test elements. But the value being compared to them is a const Test.
You need to define an operator== for Test that can handle that comparison, eg:
struct Test {
int one;
char two;
bool operator==(const Test &rhs) const {
return one == rhs.one && two == rhs.two;
/* alternatively:
return std::tie(one, two) == std::tie(rhs.one, rhs.two);
*/
}
/* alternatively in C++20 onwards:
bool operator==(const Test &) const = default;
*/
};

Can't remove element by ID from vector of non primitive datatypes

I have a vector of my user-defined data type city. I'm trying to remove an element from this vector by its ID; eventually all cities will be removed from this list in a while(!cityList.empty()) loop. I plan to use the erase-remove idiom to accomplish this.
However, I'm getting a very gnarly error message when I make my code after calling remove(). Passing in the city object as the third parameter to remove() results in this error, as does passing in the (int) ID of the city. This error doesn't occur with erase(), but does with remove(), and also find() if I try to use that. Here is the code in question:
vector<city> cityList;
cityList.push_back(city(1));
cityList.push_back(city(2));
cityList.push_back(city(3));
city cityToRemove = cityList[0];
int idOfCityToRemove = cityList[0].getID();
remove(cityList.begin(), cityList.end(), cityToRemove);
//remove(cityList.begin(), cityList.end(), idOfCityToRemove);
Here is an updated simple, minimal demo of my problem.
The error message includes "template argument deduction/substitution failed" and "‘city’ is not derived from ‘const _gnu_cxx::__normal_iterator<_IteratorL, _Container>’ " messages, and I haven't been able to find anything online relating to my problem with the above errors.
Edit: I've modified my code such that I now have:
int main(int argc, char** argv) {
vector<city> cityList;
cityList.push_back(city(1));
cityList.push_back(city(2));
cityList.push_back(city(3));
city cityToRemove = cityList[0];
int idOfCityToRemove = cityList[0].getID();
int i;
for (i = 0; i < cityList.size(); i++) {
cityList.erase(remove_if(cityList.begin(), cityList.end(), cityList[i] == cityToRemove), cityList.end());
}
//remove(cityList.begin(), cityList.end(), cityToRemove);
//remove(cityList.begin(), cityList.end(), idOfCityToRemove);
return 0;
}
bool operator ==(const city &a, const city &b)
{
return (a.id == b.id);
}
and the error I receive when attempting to compile is:
In file included from /usr/include/c++/5/bits/stl_algobase.h:71:0,
from /usr/include/c++/5/bits/char_traits.h:39,
from /usr/include/c++/5/ios:40,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from main.cpp:2:
/usr/include/c++/5/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Iter_pred<_Predicate>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<city*, std::vector<city> >; _Predicate = bool]’:
/usr/include/c++/5/bits/stl_algo.h:866:20: required from _ForwardIterator std::__remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<city*, std::vector<city> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<bool>]’
/usr/include/c++/5/bits/stl_algo.h:936:30: required from ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = __gnu_cxx::__normal_iterator<city*, std::vector<city> >; _Predicate = bool]’
main.cpp:30:90: required from here
/usr/include/c++/5/bits/predefined_ops.h:234:30: error: expression cannot be used as a function
{ return bool(_M_pred(*__it)); }
^
This is closer, but I'm not sure what is required. The line main.cpp:30:90 points to the cityList[i] == cityToRemove part of my cityList.erase() function, however, so I know that the issue is within my comparison expression.
My demo is also updated.
You need to define an operator ==:
class city {
public:
city(int idin);
int getID();
private:
int id;
friend bool operator==(const city &a, const city &b);
};
.
bool operator ==(const city &a, const city &b)
{
return a.id == b.id;
}
and also call erase as in the example here.

Using std::stable_sort with a array of pointer to functions

I'm trying to implement a class which i can use to sort a list of files based on some different functions of sort.
I'm having trouble to use an array of pointer to function to make calls.
FileList.hpp :
class FileList
{
public:
enum sortStyle{EXTENSION, NAME, SIZE, DURATION, PATH};
//...
};
namespace SortFiles
{
struct sortFcts{
FileList::sortStyle sort;
bool (*fonc)(const FileData &, const FileData &);
};
bool sortExtension(const FileData &a, const FileData &b);
bool sortName(const FileData &a, const FileData &b);
bool sortDuration(const FileData &a, const FileData &b);
bool sortSize(const FileData &a, const FileData &b);
bool sortPath(const FileData &a, const FileData &b);
}
struct SortFiles::sortFcts tabSortFctsFileList[5] = {{FileList::EXTENSION, &SortFiles::sortExtension},
{FileList::NAME, &SortFiles::sortName},
{FileList::SIZE, &SortFiles::sortSize},
{FileList::DURATION, &SortFiles::sortDuration},
{FileList::PATH, &SortFiles::sortPath}};
FileList.cpp :
void FileList::sort(FileList::sortStyle a)
{
//std::stable_sort((this->_data).begin(), (this->_data).end(), SortFiles::sortPath);
std::stable_sort((this->_data).begin(), (this->_data).end(), tabSortFctsFileList[a]);
}
Where tabSortFctsFileList[] is just a tab of my struct where i put all my sorting methods.
My problem here is that if I use the commented way it works, but when i use the array i have a compilation error I don't know why. I know i can use a huge switch and it'll work fine but i don't want to.
Here's one of the line of the error message :
/usr/include/c++/4.8/bits/stl_algo.h:
In instantiation of ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<FileData*, std::vector<FileData> >; _Compare = SortFiles::sortFcts]’:
/usr/include/c++/4.8/bits/stl_algo.h:3510:49:
required from ‘void std::__inplace_stable_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<FileData*, std::vector<FileData> >; _Compare = SortFiles::sortFcts]’
/usr/include/c++/4.8/bits/stl_algo.h:5710:52:
required from ‘void std::stable_sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<FileData*, std::vector<FileData> >; _Compare = SortFiles::sortFcts]’
FileList.cpp:71:88: required from here
/usr/include/c++/4.8/bits/stl_algo.h:2159:29: error: no match for call to ‘(SortFiles::sortFcts) (FileData&, FileData&)’
if (__comp(*__i, *__first))
I feel like the problem here is that I shouldn't use a (*fonc) but rather a fonc as last parameter, but I already tried to do something like : (Tab[a]) but it says i have no match for operator.
What should I do to fix it ?
You are trying to pass an object of type sortFcts as the predicate parameter of std::stable_sort(). Objects are type sortFcts are not callable, though. There are two simple fixes:
The simpler [and recommended] fix is to just get the fonc member of the object:
... tabSortFctsFileList[a].fonc ...
Make objects of type sortFcts callable as a predicate by adding a suitable function call operator:
struct sortFcts {
// ...
bool operator()(const FileData &a, const FileData &b) const {
return this->fonc(a, b);
}
};

std vector no match for operator ==

I'm stuck at this error:
gcc.compile.c++
Physics/HelicityAmplitude/bin/gcc-4.8.3/debug/HelicityDecayTree.o In
file included from
/cvmfs/cluster/gcc/gcc-4.8.3/include/c++/4.8.3/algorithm:62:0,
from /cluster/compwa_externals/boost_1_55_0/include/boost/move/algorithm.hpp:23,
from /cluster/compwa_externals/boost_1_55_0/include/boost/move/move.hpp:24,
from /cluster/compwa_externals/boost_1_55_0/include/boost/unordered/detail/util.hpp:19,
from /cluster/compwa_externals/boost_1_55_0/include/boost/unordered/detail/buckets.hpp:14,
from /cluster/compwa_externals/boost_1_55_0/include/boost/unordered/detail/table.hpp:10,
from /cluster/compwa_externals/boost_1_55_0/include/boost/unordered/detail/equivalent.hpp:14,
from /cluster/compwa_externals/boost_1_55_0/include/boost/unordered/unordered_set.hpp:17,
from /cluster/compwa_externals/boost_1_55_0/include/boost/unordered_set.hpp:16,
from /cluster/compwa_externals/boost_1_55_0/include/boost/graph/adjacency_list.hpp:21,
from Physics/HelicityAmplitude/HelicityDecayTree.hpp:17,
from Physics/HelicityAmplitude/HelicityDecayTree.cpp:12:
/cvmfs/cluster/gcc/gcc-4.8.3/include/c++/4.8.3/bits/stl_algo.h: In
instantiation of ‘_RandomAccessIterator
std::__find(_RandomAccessIterator, _RandomAccessIterator, const _Tp&,
std::random_access_iterator_tag) [with _RandomAccessIterator =
__gnu_cxx::__normal_iterator >; _Tp =
HelicityFormalism::ParticleState]’:
/cvmfs/cluster/gcc/gcc-4.8.3/include/c++/4.8.3/bits/stl_algo.h:4441:45:
required from ‘_IIter std::find(_IIter, _IIter, const _Tp&) [with
_IIter = __gnu_cxx::__normal_iterato r >; _Tp =
HelicityFormalism::ParticleState]’
Physics/HelicityAmplitude/HelicityDecayTree.cpp:59:61: required from
here
/cvmfs/cluster/gcc/gcc-4.8.3/include/c++/4.8.3/bits/stl_algo.h:166:17:
error: no match for ‘operator==’ (operand types are
‘HelicityFormalism::ParticleState’ and ‘const Helicit
yFormalism::ParticleState’)
if (*__first == __val)
I see that he is asking for a const to non-const comparison of ParticleState. However I don't really understand why he is asking for this comparison. My relevant code is the following:
The header for the class:
class HelicityDecayTree {
boost::adjacency_list<> decay_tree_;
std::vector<ParticleState> particles_;
public:
void createDecay(const ParticleState &mother,
const ParticleStatePair &daughters);
}
And the source for that member function:
void HelicityDecayTree::createDecay(const ParticleState &mother,
const ParticleStatePair &daughters) {
// add particles to the list
unsigned int mother_vector_index;
unsigned int daughter1_vector_index;
unsigned int daughter2_vector_index;
if (std::find(particles_.begin(), particles_.end(), mother)
== particles_.end()) {
mother_vector_index = particles_.size();
particles_.push_back(mother);
}
else {
mother_vector_index = std::distance(particles_.begin(),
std::find(particles_.begin(), particles_.end(), mother));
}
if (std::find(particles_.begin(), particles_.end(), daughters.first)
== particles_.end()) {
daughter1_vector_index = particles_.size();
particles_.push_back(daughters.first);
}
else {
daughter1_vector_index = std::distance(particles_.begin(),
std::find(particles_.begin(), particles_.end(), daughters.first));
}
if (std::find(particles_.begin(), particles_.end(), daughters.second)
== particles_.end()) {
daughter2_vector_index = particles_.size();
particles_.push_back(daughters.second);
}
else {
daughter2_vector_index = std::distance(particles_.begin(),
std::find(particles_.begin(), particles_.end(), daughters.second));
}
// then make the correct inserts into the vector and link appropriately
boost::add_edge(mother_vector_index, daughter1_vector_index, decay_tree_);
boost::add_edge(mother_vector_index, daughter2_vector_index, decay_tree_);
}
And the ParticleState struct:
struct ParticleState {
int particle_id_;
std::string name_;
Spin J_;
Spin M_;
};
Afaiu he should be synthesizing the operator== for two const ParticleStates, but for some reason the find method is asking for a non-const version for 1 argument...
Thx in advance,
Steve
Ok I forgot that the compiler will not synthesize the operator==. So I was just missing
bool operator==(const ParticleState &rhs) const {
...
}