Jay
Jay

Reputation: 2946

c++ pass member function

I'm trying to make a class that can run a function a large number of times and tell me the average amount of time the function takes to execute.

My solution uses

template<class T_ret = void, class ... T_args>
void RunNewTiming(string outputFileName, T_ret(*function)(T_args ...), int iterations = 1, T_args ... otherArgs);

It works for global functions like this

void foo(){
    // code
}

bool bar(int & a, char b){
    // more code
}

FunctionTimer functionTimer;

functionTimer.RunNewTiming("TimingForFoo", &foo, 1000);

functionTimer.RunNewTiming<bool, int , char>("TimingForBar", &bar, 1000, 5, 'h');

But if I try to pass in a public function of an object like

class Object{
public:
    void func(){
        // code
    };
}

Object obj;

functionTimer("TimingForObjFunc", obj.func, 1000);

I get the error

A pointer to a bound function may only be used to call the function

Anywhere I try to look for this error only gets people accidentally missing a () when trying to call a function, and people pointing out that they accidentally missed a () as a solution, I can't find a solution in this context.

Is it possible to pass a non-static member function like this at all? Or is there some deeper reason why this isn't working

Upvotes: 1

Views: 61

Answers (2)

TonySalimi
TonySalimi

Reputation: 8437

I propose the below solution as well:

bool bar(int & a, char b) 
{
   return true;
}

class FunctionTimer
{
public:

   double my_foo(double a)
   {
      return a + 10;
   };

   template<typename Func, typename... Args>
   void RunNewTimingEx(std::string output_file_name, int iterations, Func f, Args... args)
   {
      f(args...);
   };
};

int main()
{
   FunctionTimer test;
   auto f_1 = std::bind(std::mem_fn(&FunctionTimer::my_foo), test, std::placeholders::_1);
   auto f_2 = std::bind(&bar, std::placeholders::_1, std::placeholders::_2);

   test.RunNewTimingEx("TimingForMyFoo", 1000, f_1, 2.0);
   test.RunNewTimingEx("TimingForBar", 100, f_2, 2, 'h');

   return 0;
}

Upvotes: 1

Jay
Jay

Reputation: 2946

Update:

I actually found a solution to this problem, I needed to pass in the caller type and an instance of this object

I could then use the type to scope-operate to the correct function, T_caller::*function

template<class T_caller, class T_ret = void, class ... T_args >
auto RunNewTiming(string name, T_ret(T_caller::*function)(T_args ...), T_caller*, int iterations = 1, T_args ... otherArgs);

Then call it like

    ft.RunNewTiming<Object>("objTime", &Object::func, &obj, 1000);

Upvotes: 1

Related Questions