Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass to sort predicate that is a member function, from the constructor

I have the following code :

template <class T>
class GenericGeneticSolver
{
public:
    GenericGeneticSolver(IGenticSolverHelper<T>& helper, int generationSize) : mSolverHelper(helper), mGenerationSize(generationSize)
    {
        mCurrentGeneration.resize(mGenerationSize);
        for(int i=0;i<mGenerationSize;i++)
        {
            mSolverHelper.GenerateRandomSolution(mCurrentGeneration[i]);
        }

        sort(mCurrentGeneration.begin(),mCurrentGeneration.end(), solutionComparer);
    }
    void Evolve(int numberOfGenerations = 1)
    {
        //sort(mCurrentGeneration.begin(),mCurrentGeneration.end(), solutionComparer);
    }
private :
    int mGenerationSize;
    vector<T> mCurrentGeneration;
    IGenticSolverHelper<T>& mSolverHelper;

    bool solutionComparer (T first,T second) { return (mSolverHelper.Cost(first)<mSolverHelper.Cost(second)); }
};

In the constructor I'm filling a vector with members, and then I'm trying to sort this vector by passing a predicate to the Sort function, the predicate is a member function called `solutionComparer.

Unfortunately it does not compile, the compiler is not happy with using pointer to member functions in the constructor, i tried the same line in the "Evolve" function, and it does compile.

The error i get is :

error C3867: 'GenericGeneticSolver<T>::solutionComparer': function call missing argument list; use '&GenericGeneticSolver<T>::solutionComparer' to create a pointer to member

I tried to do what the error suggested but it didn't compile either (some random error in the sort function).

Why can't i use pointer to a member function in the constructor ?

like image 209
OopsUser Avatar asked Dec 01 '22 19:12

OopsUser


1 Answers

std::sort requires a comparator which can simply be called as compare(a,b). A (pointer to a) member function isn't suitable, since it requires an object to be called on, so you'll need a wrapper to bind the member function to an object and make it callable with just the two values to compare.

In C++11, you can bind a member function to an object:

sort(mCurrentGeneration.begin(),mCurrentGeneration.end(),
    std::bind(&GenericGeneticSolver::solutionComparer, this, 
         std::placeholders::_1, std::placeholders::_2));

or you can use a lambda:

sort(mCurrentGeneration.begin(),mCurrentGeneration.end(),
    [this](T first,T second) { return solutionComparer(first, second); });

Historically, you would have to make your own functor, perhaps along the lines of:

struct SolutionComparer {
    IGenticSolverHelper<T>* helper;

    SolutionComparer(IGenticSolverHelper<T>& helper) : helper(&helper) {}

    bool operator()(T first,T second) {
        return helper->Cost(first) < helper->Cost(second);
    }
};

sort(mCurrentGeneration.begin(),mCurrentGeneration.end(),
    SolutionComparer(mSolverHelper));
like image 136
Mike Seymour Avatar answered Dec 21 '22 23:12

Mike Seymour