views:

156

answers:

3

trying to compile the following code I get this compile error, what can I do?


ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.

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

};
+5  A: 

doCompare must be static. If doCompare needs data from MyClass you could turn MyClass into a comparision functor by changing:

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

into

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

and calling:

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

Also, isn't doSort missing a return value?

I think it should be possible to use std::mem_fun and some sort of binding to turn the member function into a free function, but the exact syntax evades me at the moment.

EDIT: Doh, std::sort takes the functor by value which may be a problem. To get around this wrap the functor inside the class:

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
There is still a problem in this solution. STL sort called the distructor of the object that is passed to it as comparator, this would ruin my program !!!
Navid
@Navid Look at my edited answer.
Andreas Brinck
+2  A: 

As Andreas Brinck says, doCompare must be static (+1). If you HAVE TO have a state in your comparator function (using the other members of the class) then you'd better use a functor instead of a function (and that will be faster):

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

Using a functor is always better, just longer to type (that can be unconvenient but oh well...)

I think you can also use std::bind with the member function but I'm not sure how and that wouldn't be easy to read anyway.

Klaim
+1  A: 

There is a way to do what you want, but you need to use a small adaptor. As the STL doesn't write it for you, can can write it yourself:

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

Then, you can use it:

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