可以将比较函数排序成成员函数的指针吗?

时间:2014-07-14 11:10:00

标签: c++ sorting member-function-pointers

我想要一个按极角对点矢量进行排序的函数,但我希望能够选择原点和方向(例如,使用Graham扫描计算凸包,需要按点排序极角相对于最底部/最左边的点)。为了避免为原点和方向创建全局变量,我将它们隐藏在类myComparisonClass中。这是我的代码:

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 */
}

有什么问题?是否可以使用&#34; sort&#34;使用比较函数,它是非静态成员函数的指针? 感谢

2 个答案:

答案 0 :(得分:4)

非静态成员函数需要调用对象。

在您的情况下,您可以使用lambda函数,如下所示:

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

或将您的课程更改为重命名 myComparisonFunctionoperator ()并直接传递obj仿函数(std::sort(P.begin(), P.end(), obj))。

答案 1 :(得分:3)

无法将指向非静态成员函数的指针传递给std::sort:该函数需要能够在没有对象引用的情况下调用比较函数,这不是你可以用成员函数。

对于像你这样的情况,你需要传递一个函数对象,它有一个运算符(),它将两个对象进行比较:

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));
}