Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Sorting set using custom comparator in a container class

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

like image 455
Michael Grinnell Avatar asked Nov 09 '17 18:11

Michael Grinnell


People also ask

How do you create a custom comparator for a set?

auto cmp = [](int a, int b) { return ... }; std::set<int, decltype(cmp)> s; We use lambda function as comparator. As usual, comparator should return boolean value, indicating whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.

Can we use comparator in set in C++?

By default std::set uses the operator < for comparing two elements and but if user passes the external sorting criteria i.e. comparator then it uses it instead of default operator < .

How does custom comparator work?

Custom Comparator are used to compare the objects of user-defined classes. The above comparator function comp() take two pair of objects at a time and return true if data members of the two operators are the same. There can be any condition as per the need of the problem in the comparator function.

How do you define a comparator in C++?

Comparator Classes are used to compare the objects of user-defined classes. In order to develop a generic function use template, and in order to make the function more generic use containers, so that comparisons between data can be made.


1 Answers

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.

like image 62
Slava Avatar answered Nov 14 '22 22:11

Slava