问题sorting使用成员函数作为比较

试图编译下面的代码我得到这个编译错误,我能做什么?


ISO C ++禁止采用非限定或带括号的非静态成员函数的地址来形成指向成员函数的指针。

class MyClass { int * arr; // other member variables MyClass() { arr = new int[someSize]; } doCompare( const int & i1, const int & i2 ) { // use some member variables } doSort() { std::sort(arr,arr+someSize, &doCompare); } }; 

doCompare必须是static 。 如果doCompare需要MyClass数据,则可以通过更改以下命令将MyClass转换为比较doCompare函数:

 doCompare( const int & i1, const int & i2 ) { // use some member variables } 

 bool operator () ( const int & i1, const int & i2 ) { // use some member variables } 

并呼吁:

 doSort() { std::sort(arr,arr+someSize, *this); } 

另外,是不是doSort缺less一个返回值?

我认为应该可以使用std::mem_fun和某种绑定来将成员函数转换为一个自由函数,但是确切的语法在此刻回避了我。

编辑:嘿, std::sort需要函数的价值,这可能是一个问题。 为了解决这个问题,在课堂上包装了函子:

 class MyClass { struct Less { Less(const MyClass& c) : myClass(c) {} bool operator () ( const int & i1, const int & i2 ) {// use 'myClass'} MyClass& myClass; }; doSort() { std::sort(arr,arr+someSize, Less(*this)); } } 

正如Andreas Brinck所说,doCompare必须是静态的(+1)。 如果你必须在你的比较函数中使用一个状态(使用类的其他成员),那么你最好使用一个函数而不是函数(这将更快):

 class MyClass{ // ... struct doCompare { doCompare( const MyClass& info ) : m_info(info) { } // only if you really need the object state const MyClass& m_info; bool operator()( const int & i1, const int & i2 ) { // comparison code using m_info } }; doSort() { std::sort( arr, arr+someSize, doCompare(*this) ); } }; 

使用仿函数总是更好,只要input更长的时间(这可能是不方便的,但哦…)

我想你也可以使用std :: bind与成员函数,但我不知道如何也不会很容易阅读。

更新2014年:今天我们可以访问c ++ 11编译器,所以你可以使用lambda代码,代码会更短,但具有完全相同的语义。

你可以使用boost::bind

 void doSort() { std::sort(arr,arr+someSize, boost::bind(&MyClass::doCompare, this, _1, _2)); } 

Rob提出的解决scheme现在是有效的C ++ 11(不需要Boost):

 void doSort() { using namespace std::placeholders; std::sort(arr, arr+someSize, std::bind(&MyClass::doCompare, this, _1, _2)); } 

事实上,正如Klaim所提到的,lambda是一个选项,有点冗长(你必须“重复”参数是整数):

 void doSort() { using namespace std::placeholders; std::sort(arr, arr+someSize, [this](int l, int r) {return doCompare(l, r); }); } 

C ++ 14在这里支持auto

 void doSort() { using namespace std::placeholders; std::sort(arr, arr+someSize, [this](auto l, auto r) {return doCompare(l, r); }); } 

但是,您仍然声明参数是通过复制传递的。

那么问题是“哪一个最有效率”。 Travis Gockel对待这个问题: Lambda vs Bind 。 他的基准testing程序在我的电脑上(OS X i7)

  Clang 3.5 GCC 4.9 lambda 1001 7000 bind 3716166405 2530142000 bound lambda 2438421993 1700834000 boost bind 2925777511 2529615000 boost bound lambda 2420710412 1683458000 

lambda是直接使用的lambda, lambda bound是一个存储在std::function的lambda。

所以看来lambda是一个更好的select,因为编译器提供了更高级别的信息,从中获利,这并不太令人意外。

有办法做你想做的,但你需要使用一个小的适配器。 由于STL不会为你写,所以你可以自己写:

 template <class Base, class T> struct adaptor_t { typedef bool (Base::*method_t)(const T& t1, const T& t2)); adaptor_t(Base* b, method_t m) : base(b), method(m) {} adaptor_t(const adaptor_t& copy) : base(copy.base), method(copy.method) {} bool operator()(const T& t1, const T& t2) const { return (base->*method)(t1, t2); } Base *base; method_t method; } template <class Base, class T> adaptor_t<Base,T> adapt_method(Base* b, typename adaptor_t<Base,T>::method_t m) { return adaptor_t<Base,T>(b,m); } 

那么,你可以使用它:

 doSort() { std::sort(arr,arr+someSize, adapt_method(this, &doCompare)); } 

有效使用成员函数的一个非常简单的方法是使用operator <。 也就是说,如果你有一个叫做compare的函数,你可以从operator <来调用它。 这是一个工作的例子:

 class Qaz { public: Qaz(int aX): x(aX) { } bool operator<(const Qaz& aOther) const { return compare(*this,aOther); } static bool compare(const Qaz& aP,const Qaz& aQ) { return aP.x < aQ.x; } int x; }; 

那么你甚至不需要把函数名称给std :: sort:

 std::vector<Qaz> q; q.emplace_back(8); q.emplace_back(1); q.emplace_back(4); q.emplace_back(7); q.emplace_back(6); q.emplace_back(0); q.emplace_back(3); std::sort(q.begin(),q.end()); 

更新Graham Asher的答案,因为你不需要比较,但可以直接使用less运算符。

 #include <iostream> #include <vector> #include <algorithm> using namespace std; class Qaz { public: Qaz(int aX): x(aX) { } bool operator<(const Qaz& aOther) const { return x < aOther.x; } int x; }; int main() { std::vector<Qaz> q; q.emplace_back(8); q.emplace_back(1); q.emplace_back(4); q.emplace_back(7); q.emplace_back(6); q.emplace_back(0); q.emplace_back(3); std::sort(q.begin(),q.end()); for (auto& num : q) std::cout << num.x << "\n"; char c; std::cin >> c; return 0; }