Functor. Implementing comparator with additional parameter



  • Hi.
    Im trying to implement a comparator to sort my QList<Custom>. Problem ist, the comparator for qSort obv have to be a static function, just taking two arguments. But i need a third argument, so i can do my comparison, or i need somehow to access member variables of my class. Is there a way to do this?
    I came across something called functor, that somehow make a subclass of myclass and then use member variables and implementing "operator()" , but i dont get how to do it and if its even possible with the signal and slot stuff.


  • Lifetime Qt Champion

    Hi,

    Can you show a sample of how you would like to do your comparison ?



  • Well, i have a QList<Village> containing villages with a name and two coordinates. I have a program that display i number of villages in a TableView. I want to sort the villages with respect to their distance to a specific targetvillage. Which means the sorting changes every time the targetvillage is changed. This means i need an additional argument for the comparison, namely a pointer, reference or whatever for the current targetvillage.

    class Village
    {
    public:
    ...
    
    private:
        QString villageName;
        int x;
        int y;
    };
    

    so far i had something like

    
     void TableDataModel::sort(int column, Qt::SortOrder order)
     {
           qSort(villageList->begin(), villageList->end(), compareTwoVillageLessThan);
     }
    
    bool TableDataModel::compareTwoVillageLessThan(const Village &A, const Village &B )
    {
        Village tempTargetVillage = *targetVillage;
        double distanceA = calculateDistance::getCalculateDistance(A, tempTargetVillage, c);
        double distanceB = calculateDistance::getCalculateDistance(B, tempTargetVillage, c);
        return distanceA < distanceB;
    }
    

    but then i realized the comparator have to be static and i cant access class member.


  • Lifetime Qt Champion

    Use a functor:

    class CompareTwoVillages
    {
    private:
       const Village refVillage;
    
    public:
    
       CompareTwoVillages(const Village &village) : refVillage(village)
       {
       }
    
       bool operator () (const Village& leftVillage, const Village& rightVillage)
       {
            bool result = false;
            // implement algorithm
            return result;
       }
    };
    

    And then call:

    qSort(villageList.begin(), villageList.end(), CompareTwoVillages(targetVillage));
    

    By the way, why do you allocate your QList on the heap ? That's usually not needed.


  • Qt Champions 2016

    @Maser
    I have two tiny remarks to the otherwise excellent guidance provided by @SGaist:

    1. You could use a lambda function (which internally is a functor) instead of writing a whole class. It's just a more compact notation for what Samuel suggested.
    2. You should use std::sort instead of qSort, as qSort is marked obsolete in Qt 5.

    Kind regards.



  • Thank you very much, guys))
    Your example helped me a lot, SGaist. Although i had to do a bit of reading on functors and function pointers to fully understand the concept.
    I let it sink in a bit, and then im gonna read some more on lambdafunctions as kshegunov suggested.
    Thubms up!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.