I have a class named Customer which is overloading the < operator:
bool Customer::operator<(const Customer &other) {
return this->price < other.price;
}
but when I try to initialize the priority queue I get pages of errors.
Customer c1(10,5,12,30);// last parameter is price
Customer c2(10,5,12,2);
priority_queue<Customer , vector<Customer> , less<Customer> > barQ;
barQ.push(c2);
barQ.push(c1);
cout<<barQ.top().price;
Then, i accidentally found out that when i initialize it in following way:
Customer c1(10,5,12,30);
Customer c2(10,5,12,2);
priority_queue<Customer* , vector<Customer*> , less<Customer*> > barQ;
barQ.push(&c2);
barQ.push(&c1);
cout<<barQ.top()->price;
I got no errors and it works well.
So my question is that what's the difference between Customer & Customer*?
I thought it should work when I declare it with Customer, NOT Customer* , why it works otherwise?
The signature of std::less::operator() is (taken from cppreference):
bool operator()( const T& lhs, const T& rhs ) const; // (until C++14)
constexpr bool operator()( const T& lhs, const T& rhs ) const; //(since C++14)
Note the it takes both parameters as const, thus it can only call a const operator<:
bool Customer::operator<(const Customer &other) const { // <--- add const here
return this->price < other.price;
}
Your second code is not really doing what you want it to do, because it uses the built-in operator< for pointers.
you are missing const in operator overload
bool operator<(const Customer &other) const {
return this->price < other.price;
}
you can also use your own comparator instead of std::less. Here is how we can write it.
template<typename type>
struct mycomp {
bool operator()(const type & first, const type & second) const {
return first.price < second.price;
}
};
struct Customer {
int price;
};
int main(){
Customer c1{3};// last parameter is price
Customer c2{2};
priority_queue<Customer , vector<Customer> , mycomp<Customer> > barQ;
barQ.push(c2);
barQ.push(c1);
cout<<barQ.top().price;
return 0;
}
set::less<> doesn't gives an error with Customer* pointer because pointers comparisons can happen as int and it doesn't look for the custom implementation. which is not the case with Customer.
Related
I have this struct
struct C {
int ID;
int age;
C(int ID, int age) : ID{ID}, age{age} {}
};
I use a comparator function for a multiset
bool fncomp (const C& lhs, const C& rhs) {
return lhs.age < rhs.age;
}
multiset<C, decltype(fncomp)*> ms{fncomp};
ms.emplace(1, 15);
...
// this works fine
ms.count(C(1, 15));
However if I use a class comparator, this is no longer working.
struct classcomp {
bool operator() (const C& lhs, const C& rhs) {
return lhs.age < rhs.age;
}
};
multiset<C, classcomp> ms;
ms.emplace(1, 15);
...
// error
// ms.count(C(1, 15));
Anything makes the two different?
Elaborating on my comment above:
multiset::count is a const member function, which means that it operates on a const multiset. This includes the member variables of the multiset. The comparator is a member variable of the multiset.
Since your classcomp::operator() is not marked const, it can't be called on a const object, and so it fails to compile.
This works for the function pointer example, because it's the pointer that is const in that case.
bool operator() (const C& lhs, const C& rhs) const {
return lhs.age < rhs.age;
}
This would fix things to compile in this link you provided, courtesy of #Marshall -> https://stackoverflow.com/a/71384594/10630957
I would like to overload possibly the string operator of my class so that I can count the number of element inserted into a std::multiset based on the key.
I would like to get the total object of type "a" given the following class:
class Item
{
public:
Item();
Item(std::string type, float price);
friend bool operator <(const Item & lhs, const Item & rhs);
friend bool operator == (const Item & lhs, const Item & rhs);
virtual ~Item();
private:
std::string type_;
float price_;
};
bool operator<(const Item & lhs, const Item & rhs)
{
return (lhs.price_ < rhs.price_);
}
bool operator == (const Item & lhs, const Item & rhs)
{
return (lhs.type_ == rhs.type_);
}
int main(){
Item a("a", 99999);
Item b("b", 2);
Item c("c", 5);
Item d("d", 5);
Item e("e", 555);
Item f("f", 568);
Item g("a", 99999);
std::multiset <Item> items_;
items_.insert(a);
items_.insert(b);
items_.insert(c);
items_.insert(d);
items_.insert(g);
items_.insert(a);
auto tota = items_.count("a");
return 0;
}
And I would expect tota to return 2 in this case.
However I am not sure to know how to proceed.
Instead of
auto tota = items_.count("a");
use
auto tota = items_.count(Item("a", 0));
The price can be anything since you don't use it in the operator< function.
I misspoke about the operator< function. It IS using price. If you want to be able to lookup by just the type, you need to change it to:
bool operator<(const Item & lhs, const Item & rhs)
{
return (lhs.type_ < rhs.type_);
}
If you want to be able to search for Items using just a string, you might want to use a std::multimap<std::string, Item> instead of std::multiset<Item>.
I am sorry if there is similar questions already present on the website, but am currently failing to understand certain parts of the algorithm.
I have a Struct that contains information on user account information for my game:
struct Account
{
int Position;
string Name;
int Score;
string Date;
int Level;
bool operator < (User SOMETHING, User SOMETHING)
{
return (SOMETHING < SOMETHING);
}
};
vector<Account> User;
User.push_back(Account());
User.push_back(Account());
User.push_back(Account());
User[0].Position=1;
User[1].Position=2;
User[2].Position=3;
sort(User.begin(), User.end(), Account);
I need each struct of my vector to be to be organized, say for instance, in descending/ascending order for the "Position" value that each contains.
I just need help on (1) bool operator function (e.g. parameters and return values), and (2) How do I have it so that I can sort it by multiple variables like the positions, scores & level. (Would I need to have 3 bool operator functions?)
Use std::tie, something like this:
struct Account
{
int Position;
string Name;
int Score;
string Date;
int Level;
};
bool operator < (const Account& lhs, const Account& rhs)
{
return std::tie(lhs.Name,lhs.Score,lhs.Date) < std::tie(rhs.Name,rhs.Score,rhs.Date);
}
will sort according to Name first, if Name is equal then according to Score, when both Name and Score are equal then according to Date.
Sorting is simply done by:
std::sort(User.begin(), User.end());
Which, by default, uses operator< on the contained objects of type Account.
Update: I misunderstood your question. In your case you need separated comparators, e.g.
struct by_name_ascending
{
bool operator()(const Account& lhs, const Account& rhs) const
{
return lhs.Name < rhs.Name;
}
};
struct by_score_descending
{
bool operator()(const Account& lhs, const Account& rhs) const
{
return lhs.Score > rhs.Score;
}
};
and sort the vector with
std::sort(User.begin(), User.end(), by_name_ascending());
With lambdas, you could also use
std::sort(User.begin(), User.end(),
[](const Account& lhs, const Account& rhs){
return lhs.Name < rhs.Name;
}
);
directly, simply switching < and > for ascending/descending. No need for other helpers or operators in the class/struct itself.
I have a class like this:
class AI
{
private:
struct Comparator
{
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) > GetHeuristicCost(rhs);
}
};
int GetHeuristicCost(const Town* town);
// constructor and variables
};
GetHeuristicCost returns the heuristic from the town parameter to the exit of the path.
What I am trying to do is overload the bool operator for a priority queue but it gives me the error
a nonstatic member reference must be relative to a specific object
I know why it is giving me this error but what I don't know is how to use a nonstatic function inside the Comparator struct.
GetHeuristicCost must be nonstatic
I tried moving GetHeuristicCost inside the Town class to no avail
I need to overload the operator with a struct because I need to use two different bool overloadings on the () for two different circumstances but with the same parameters (two Towns). In other words I need the struct so I can't do this:
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) > GetHeuristicCost(rhs);
}
Basically I plan on having two structs like this:
struct Comparator1
{
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) > GetHeuristicCost(rhs);
}
};
struct Comparator2
{
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) + GetTotalCost (lfs, rhs) > GetHeuristicCost(rhs) + GetTotalCost (lfs, rhs);
}
};
You need to construct instances of the Comparator nested class with a pointer/reference to their "outer" class instance.
class AI
{
private:
struct Comparator
{
const AI &outer;
Comparator(const AI &o):outer(o){}
bool operator()(const Town* lfs, const Town* rhs)const
{
return outer.GetHeuristicCost(lfs) > outer.GetHeuristicCost(rhs);
}
};
int GetHeuristicCost(const Town* town)const;
};
// how to use in code:
AI::Comparator comp(*this);
priority_queue<Town*, vector<Town*>, AI::Comparator> priorityQueue(comp);
I am trying to sort a vector of custom struct in C++
struct Book{
public:int H,W,V,i;
};
with a simple functor
class CompareHeight
{
public:
int operator() (Book lhs,Book rhs)
{
return lhs.H-rhs.H;
}
};
when trying :
vector<Book> books(X);
.....
sort(books.begin(),books.end(), CompareHeight());
it gives me exception "invalid operator <"
What is the meaning of this error?
Thanks
sort expects a function that returns bool, which is true iff the lhs precedes the rhs:
bool operator() (const Book& lhs, const Book& rhs)
{
return lhs.H < rhs.H;
}
Also note the change to const Book& parameters, to avoid copying.