Reputation: 960
I have a class Person that has a name and an age.
I have a container class called people that stores a set of persons.
I have created two custom comparators to sort by name and by age.
When I store the set containing Persons in my class (People) how do pass the custom comparator in.
for Example
My comparator looks like this
struct compareByName
{
bool operator()(const Person & Left, const Person & Right)
{
return (Left.getName() < Right.getName());
}
};
in the main if I want to sort a set of persons by name I just do
set<Person, compareByName> peopleByName;
or for age I do
set<Person, compareByAge> peopleByAge;
Where I am having trouble is How do I use this in my people container class I would have something like
class People
{
private:
set<Person, COMPARATOR> m_people;
}
where COMPARATOR could either be by name or age
Upvotes: 5
Views: 3155
Reputation: 44238
You can use std::function
as comparator type and then provide particular comparator for constructor:
class People
{
using PeopleSet = set<Person, std::function<bool(const Person &p1, const Person &p2 )>>;
People() : people( compareByName() ) {}
void sortByAge();
private:
PeopleSet people;
};
note you cannot change comparator after creation of set, you have to create another instance:
void People::sortByAge()
{
people = PeopleSet( people.begin(), people.end(), compareByAge() );
}
and that would involve copying or moving whole set. If you want to be able to use both ways at the same time use boost::multi_index
instead.
Upvotes: 7
Reputation: 6240
You can do it via template:
#include <iostream>
#include <string>
#include <set>
class Person
{
private:
std::string name;
int age;
public:
Person(std::string name, int age) : name(name), age(age) {};
std::string getName() const { return name; };
int getAge() const { return age; };
};
template<class COMPARATOR> class People
{
private:
std::set<Person, COMPARATOR> m_people;
public:
void AddPerson(Person const &p)
{
m_people.insert(p);
}
void PrintPeople()
{
for (Person p : m_people)
{
std::cout << p.getName() << " - " << p.getAge() << std::endl;
}
}
};
struct SortedByName
{
bool operator()(const Person & Left, const Person & Right)
{
return (Left.getName() < Right.getName());
}
};
struct SortedByAge
{
bool operator()(const Person & Left, const Person & Right)
{
return (Left.getAge() < Right.getAge());
}
};
int main()
{
Person p1("Bob", 21);
Person p2("Jack", 13);
Person p3("Kath", 33);
People<SortedByName> ppl1;
ppl1.AddPerson(p1);
ppl1.AddPerson(p2);
ppl1.AddPerson(p3);
std::cout << "By Name:" << std::endl;
ppl1.PrintPeople();
std::cout << std::endl;
People<SortedByAge> ppl2;
ppl2.AddPerson(p1);
ppl2.AddPerson(p2);
ppl2.AddPerson(p3);
std::cout << "By Age:" << std::endl;
ppl2.PrintPeople();
return 0;
}
Prints:
By Name:
Bob - 21
Jack - 13
Kath - 33
By Age:
Jack - 13
Bob - 21
Kath - 33
Upvotes: 2