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

2019-07-02 12:05发布

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?

2条回答
别忘想泡老子
2楼-- · 2019-07-02 12:44

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

查看更多
▲ chillily
3楼-- · 2019-07-02 12:59

As mentioned by Mgetz, a functor can be used. Example of functor:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <vector>

#define asize 16

class example{
public:
    unsigned int a[asize];      // array
    std::vector<size_t> v;      // indices to array

example(void)
{
    v.resize(asize);
    for(size_t i = 0; i < asize; i++){
        a[i] = rand()%10;
        v[i] = i;
    }
}

void displayarray(void)
{
    for(size_t i = 0; i < asize; i++)
        std::cout << std::setw(3) << a[v[i]];
    std::cout << std::endl;
}

class lessthan                  // lessthan functor for std::sort
{
public:
const example &x;
    lessthan(const example &e ) : x(e) { }
    bool operator()(const size_t & i0, const size_t & i1)
    {
        return x.a[i0] < x.a[i1];
    }
};

void sortarray(void)
{
    std::sort(v.begin(), v.end(), lessthan(*this));
}
};

int main()
{
example x;

    x.displayarray();
    x.sortarray();
    x.displayarray();
    return 0;
}
查看更多
登录 后发表回答