Search code examples
c++stlpointer-to-membernth-element

How to call stl::nth_element with a member function inside this class?


I want to use the function nth_element with my own sorting function (which should have access to the data of the object) within a class. Currently, I am doing the following:

class Foo
{
 public:
   glm::vec3 *points;
   int nmbPoints;

   bool idxPointCompareX(int a, int b);
   void bar();
}

bool Foo::idxPointCompareX(int a, int b)
{return points[a].x < points[b].x;)

void Foo::bar()
{
   stl::vector<int> idxPointList;
   for(int i = 0; i < nmbPoints; i++) idxPointList.push_back(i);  

   stl::nth_element(idxPointList.first(),idxPointList.first()+nmbPoints/2,idxPointList.end(), idxPointCompareX);
}

Of course, this did not work and I got the error: "reference to non-static member function must be called". After that, I had a look at Reference to non-static member function must be called, How to initialize std::function with a member-function? and some other questions on here. I understand why this did not work, but I'm unsure how to solve this.

Can someone help me and tell me how to solve this problem?


Solution

  • To take the address of a member function you need to use the correct syntax, i.e. &Foo::idxPointCompareX not just idxPointCompareX

    But you also need a Foo object to call the function on, so you would need to bind one to it. Presumably you mean to call it on this so you could use std::bind:

    using namespace std::placeholders;
    stl::nth_element(begin, begin+n, end,
                     std::bind(&Foo::idxPointCompareX, this, _1, _2));
    

    Or simpler, use a lambda function:

    stl::nth_element(begin, begin+n, end, 
                     [this](int a, int b) { return idxPointCompareX(a, b);}
    );
    

    This creates a lambda function that captures this and passes its arguments on to the idxPointCompareX function on the captured this pointer.