1

I want a function that sort a vector of points by polar angle, but I want to be able to choose the point of origin and the direction (for example, for computing convex hull with Graham scan, you need to sort points by polar angle relatively to the bottommost/leftmost point). To avoid making global variables for the origin and direction, I hid them in a class myComparisonClass. Here is my code:

template<typename TT>
class myComparisonClass {
    point<TT> origin;
    point<TT> direction;
public:
    inline myComparisonClass (point<TT> or, point<TT> dir) : origin(or), direction(dir) {};

    bool myComparisonFunction(const point <TT>& a, const point<TT>& b) {  
        /* ... A function which use a, b, origin and direction ... */
        return false;
    };
};

template<typename TT>
void mySortByPolarAngle(vector<point<TT> >& P, point<TT> O, point<TT> dir) {
    myComparisonClass<TT> obj(O,dir);
    bool (myComparisonClass<TT>::* myFunctionPointer)(const point<TT>&, const point<TT>&) = &myComparisonClass<TT>::myComparisonFunction;
    sort(P.begin(), P.end(), obj.*myFunctionPointer); /* When trying to use mySortByPolarAngle, compiler says error: invalid use of non-static member function */
}

What is wrong? Is it possible to use "sort" with a comparison function which is a pointer on a non-static member function? Thanks

2 Answers 2

4

A non static member function require an object to be called.

In your case you may use a lambda function as the following:

std::sort(P.begin(), P.end(),
          [&obj](const point<TT>& lhs, const point<TT>& rhs){
              return obj.myComparisonFunction(lhs, rhs);
          });

or change your class to rename myComparisonFunction to operator () and pass your obj functor directly (std::sort(P.begin(), P.end(), obj)).

Sign up to request clarification or add additional context in comments.

Comments

3

It is not possible to pass a pointer to a non-static member function to std::sort: the function needs to be able to call the comparison function without an object reference, which is not something you can do with a member function.

For situations like yours you need to pass a function object, which has an operator () taking two objects being compared:

template<typename TT>
class myComparisonClass {
    point<TT> origin;
    point<TT> direction;
public:
    inline myComparisonClass (point<TT> or, point<TT> dir) : origin(or), direction(dir) {};

    bool operator()(const point <TT>& a, const point<TT>& b) {  
        /* ... A function which use a, b, origin and direction ... */
        return false;
    };
};
...
template<typename TT>
void mySortByPolarAngle(vector<point<TT> >& P, point<TT> O, point<TT> dir) {
    sort(P.begin(), P.end(), myComparisonClass(O, dir));
}

Comments

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.