Declaring priority_queue for user-defined class - c++

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

multiset count method not working with class comparator

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

Overloading string operator for key multiset

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

Sorting A Vector Of Structs According To Contained Data

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.

Overloading a bool operator with a member function

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);

C++ struct sorting error

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.