Search code examples
c++sortingfunctor

How to use sort() in C++ with custom sort member function?


I have a question about passing the comparison function to sort().

What I want to do is define a sort() function that takes into account for its calculation a member variable of the class that I want to do the sorting in.

Basically, my code looks like this (simplified to only show the relevant parts):

MappingTechnique.h

struct MappingTechnique {
    vector<int> usedIndexCount; 
};

struct SimpleGreedyMappingTechnique : MappingTechnique {
    bool sortByWeights(int index1, int index2);
};

MappingTechnique.m

bool SimpleGreedyMappingTechnique::sortByWeights(int index1, int index2) {
    return usedIndexCount[index1] > usedIndexCount[index2];
}

void SimpleGreedyMappingTechnique::processFrame(Frame frame) {
    vector<int> payloadIndices = <generate the vector>

    // sort the payload indices according to their current usedIndexCount
    sort(payloadIndices.begin(), payloadIndices.end(), sortByWeights);
}

This code doesn't compile, it gives the following error:

 error: reference to non-static member function must be called

and points to sortByWeights.

Is it even possible to use a member function of a class for sorting? If it is, how I can implement this?


Solution

  • It is, but in general I would encourage just using a proper functor or a lambda:

    Using a lambda:

    std::sort(payloadIndices.begin(), payloadIndices.end(), [this](int a, int b){
        return this->sortByWeights(a, b);
    });
    

    Alternatively using std::mem_fn:

    auto sorter = std::bind(std::mem_fn(SimpleGreedyMappingTechnique::sortByWeights), this);
    std::sort(payloadIndices.begin(), payloadIndices.end(), sorter);
    

    Alternatively using a functor:

    namespace{
    struct indicies_less_than
    {
        const SimpleGreedyMappingTechnique & mapping_tech;
        indicies_less_than(const SimpleGreedyMappingTechnique & mapping_tech)
           :mapping_tech(mapping_tech){}
    
        bool operator()(int a, int b)
        {
           return mapping_tech.sortByWeights(a, b);
        }
    };
    }
    
    std::sort(payloadIndices.begin(), payloadIndices.end(), indicies_less_than(*this));
    

    Note:

    if the types being sorted were anything more complicated than an int you would definitely want to pass them by const& to prevent copying