1

I am trying to pass a function pointer to a member function of a class to std::unique() and am getting some compiler errors that are impossible for me to decipher.

// So this will otherwise compile
class Vec2 {};
class Polygon {};

// ConvexHull.h:
#include <vector>
#include <algorithm>
class ConvexHull {
public:
   // Used to sort an array of vectors so the bottom-right element is first:
   bool bottomRight(const Vec2& a, const Vec2& b);
   // Used to determine if coordinates are equivalent:
   bool vecEqual(const Vec2& a, const Vec2& b);
   Polygon chGrahamScan(std::vector<Vec2> points);
};

// ConvexHull.cpp:
bool ConvexHull::bottomRight(const Vec2& a, const Vec2& b) {
  // implementation...
  return false; // So this will otherwise compile
}

bool ConvexHull::vecEqual(const Vec2& a, const Vec2& b) {
  // implementation...
  return false; // So this will otherwise compile
}

Polygon ConvexHull::chGrahamScan(std::vector<Vec2> points) {
  // Sort according to bottom right:
  std::sort(points.begin(),points.end(),bottomRight); // !!!Does not compile!!!
  std::vector<Vec2>::iterator it;
  // Get rid of duplicate points:
  it = std::unique(points.begin(),points.end(),vecEqual); // !!!Does not compile!!!
  // rest of implementation...
  Polygon poly; // So this will otherwise compile
  return poly;
}

int main(){return 0;} // again, to allow this to otherwise compile

Ignoring the two broken lines, this is enough to compile something. Please help! I am not sure what I am doing wrong here. I know this test code says the members functions are public but my end goal here is to have them be private functions that are hidden from the user but still used internally in ConvexHull::chGrahamScan() by sort and unique. These aren't the only two comparison methods I intend to use. The others require referring to internal state data maintained by an instance of the ConvexHull class. My initial solution (which apparently totally worked) had methods that did not belong to any class. Instead all of the state data and comparison functions were in a global anonymous namespace, but this broke the thread-safeness of my project so I decided to go this route.

If you copy and paste this into an empty project you should see the errors I am getting. It says I need to use .* or ->* for a member function pointer. However trying to do this gives me other errors, saying these functions cannot be used as member functions as they are of type "unresolved overloaded function".

If it turns out that I cannot do something like this, how would I best go about implementing std::sort and std::unique in such a way that the comparison functions passed to them use state data external to the definition of the functions themselves without violating thread safety by using global variables? My previous solution did something like:

namespace {
  Vec2 point0; // state data that other comparison functions like
               // bottomRight and vecEqual need
  bool bottomRight(/*...*/){/*...*/}
  bool vecEqual(/*...*/){/*...*/}
}

// Accesses global data. Bad!
Polygon chGrahamScan(std::vector<Vec2> points) {
  std::sort(points.begin(),points.end(),bottomRight);
  std::vector<Vec2>::iterator it;
  it = std::unique(points.begin(),points.end(),vecEqual);
  // etc..
}
1

2 Answers 2

2

If you want to use the sort function with a comparator, write the comparator as a separate object rather putting the code in your ConvexHull class. Unless you need some private data within ConvexHull, your comparator does not need to be part of that class.

class ConvexHull
{
    // ... rest of class as shown above ...
    private:
       // declare friend so comparator can use private data.
        friend struct VectorComparator;
};

struct VectorComparator
{
    explicit VectorComparator( ConvexHull * hull ) : hull_( hull ) {}
    bool operator()( const Vec2& a, const Vec2& b ) const
    {
        // ... compare the two Vec2 objects here using private data from ConvexHull ...
    }
    ConvexHull * hull_;
};

Then you can use VectorComparator as a parameter into std::sort.

ConvexHull * hull = new ConvexHull;
std::sort(points.begin(),points.end(), VectorComparator(hull) );

You can make a separate comparator for the unique function.

struct UniqueVectorComparator
{
    bool operator()( const Vec2& a, const Vec2& b ) const
    {
        // .. compare the two Vec2 objects here.
    }
};

it = std::unique(points.begin(),points.end(), UniqueVectorComparator() );
Sign up to request clarification or add additional context in comments.

3 Comments

I might not understand the C++ library enough. Do I then pass this class to std::sort / std::unique instead of a function pointer?
Yes, pass an instance of the comparator instead of a function pointer.
Thanks this seems like exactly the kind of solution I need!
1

As the compiler says, make your functions static and use scoping operator:

class ConvexHull {
public:
   // Used to sort an array of vectors so the bottom-right element is first:
   static bool bottomRight(const Vec2& a, const Vec2& b);
   // Used to determine if coordinates are equivalent:
   static bool vecEqual(const Vec2& a, const Vec2& b);
   Polygon chGrahamScan(std::vector<Vec2> points);
};
...
std::sort(points.begin(),points.end(),ConvexHull::bottomRight); // !!!Does not compile!!!

3 Comments

I know that bottomRight and vecEqual conceptually require no state data, but I have other comparison functions that do. Particularly I have one called anglePoint0() that orders points by their angel with respect to a certain point, which is a data member of ConvexHull. If the comparison functions are static, how can they access that data member?
@GarrettGutierrez The comparison functions could not access data members if they are static functions within ConvexHull. I can show you a way to do that by editing my answer.
@GarrettGutierrez there exists pointer to function members of instance, but you can't call them without an instance (use operator .* or ->*)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.