开发者

Saving function pointer+arguments for later use

开发者 https://www.devze.com 2023-02-08 22:02 出处:网络
I have this problem where a C++ function pointer is saved, together with a set of arguments to call it on开发者_高级运维, such that it can be called later. The calling code is unaware of the type and

I have this problem where a C++ function pointer is saved, together with a set of arguments to call it on开发者_高级运维, such that it can be called later. The calling code is unaware of the type and arguments of the functions. Saving and calling function pointers and arguments is extremely performance critical in my application. The interface should look something like this:

void func( int a, char * b );
call_this_later( func, 5, "abc" );

A straightforward solution is to put all of this information in a functor, requiring a different typedef per called function. C++11 would allow me to do that using a variadic template, so that is ok.

Since the type of the functor is not known at the point of call, it seems necessary to create a virtual base class for these functors and to invoke the functors using virtual function calls. The performance overhead of virtual function calls + heap allocation is too high (I am pushing the boundaries of implementing this idiom with as few assembly instructions as possible). So I need a different solution.

Any ideas?


You could do this with a lambda expression which captures the types.

template <typename Func, typename Arg1, typename Arg2>
std::function<void(void)> call_this_later(Func f, Arg1 a1, Arg2 a2) {
    return [=]() { f(a1, a2); }; // Capture arguments by value
}

A few things to note:

  1. I don't think you can use perfect forwarding here since you have to capture the arguments
  2. Since C++ is not garbage collected, if the arguments are pointers they may point to something that isn't alive later on. For example if your argument is const char* then it's OK if you use it with a string literal but not if you pass someStdString.c_str() and the string is going to die any-time soon.
  3. I gave the example with two arguments, if your compiler supports variadic templates you can use those otherwise just create an overload for each number of arguments.


What about a solution using boost::function / boost::bind:

void func( int a, char * b );

boost::function<void ()> my_proc = 
    boost::bind(&func, 5, "abc");

// then later...

my_proc(); // calls func(5, "abc");


You're going to need a custom allocator to match your allocation pattern. Alternatively, use compile-time polymorphism to pass the type of the functor in to the call site.

0

精彩评论

暂无评论...
验证码 换一张
取 消