Reputation: 552
I have a class, and the pointers to the objects of this class need to be placed in a std::set
. I want to define the comparator inside the class. I have seen a few solutions where either a separate class is defined (I guess it is called a functor), or a structure is defined which overloads the operator()
. I want to avoid this boilerplate code, and want to define a comparator as a member of the class itself, something along the lines of Java's compareTo()
method.
Let us say, my class is something like:
class Item {
private:
int id;
float score;
.....
public:
// Rest of the methods and setters/getters
}
I want to define the comparator in a way that pointer to object having a higher score are placed first in the set. If the score is equal for the two, then the one with the lower id is placed first. I guess the code will be something like the following, but since I did not understand this part very well, please correct me (I would like this to be placed inside the class itself):
bool operator()(const Item* a, const Item* b) {
if (a->score != b->score) return a->score > b->score;
return a->id < b->id;
}
The usage would be as follows:
std::set<Item*> sortedItems;
Item* item = new Item();
sortedItems.insert(item);
I am not sure if the comparator needs to be specified at all in the std::set
template if defined within the class, and if so, how? Also, how do I add this comparator in the class itself? I am new to STL, and fairly new to C++ as well. Thanks!
Upvotes: 2
Views: 3286
Reputation: 7249
this solution is inspired by this answer.
#include <set>
class Item {
private:
int id;
float score;
public:
struct compare {
bool operator()(const Item* a, const Item* b) {
if (a->score != b->score) return a->score > b->score;
return a->id < b->id;
}
};
};
Because set allows you to define your own comparison method you can use it as follows.
std::set<Item*, Item::compare> sortedItems;
This should allow your class Item to work with set
Upvotes: 5
Reputation: 76245
The set<T>
implementation wants to call a < b
where a
and b
are objects of type T
. As long as that call is valid, the set doesn't care; it can be a non-static member function that takes one argument, a static member function that takes two arguments, or a free function that takes two argument:
class Item {
public:
bool operator<(const Item& rhs) {
return score == rhs.score ? id < rhs.id : score < rhs.score;
}
static bool operator<(const Iterm& lhs, const Item& rhs) {
return lhs.score == rhs.score ? lhs.id < rhs.id : lhs.score < rhs.score;
}
};
bool operator<(const Item& lhs, const Item& rhs) {
return lhs.score == rhs.score ? lhs.id < rhs.id : lhs.score < rhs.score;
}
Any one of those three is okay. Of course, if you write two or more of them, you'll get ambiguities.
Upvotes: 2