I'm having trouble passing a C++0x lambda function as the second argument to makecontext
(from ucontext.h). The signature of makecontext
is:
void makecontext(ucontext_t*, void (*)(), int, ...);
Previously, I was able to apply a C-style (void (*)(void))
cast, to the global scope functions I used. A reinterpret_cast
would do the trick in C++. However, with a C++0x lambda function, I get the following error:
error: invalid cast from type ‘main(int, char**)::<lambda(int)>’ to type ‘void (*)()’
I'm using G++ 4.6. The following code is sufficient to produce the compile error:
#include <ucontext.h>
void f1(int i) {}
int main(int argc, char *argv[]) {
ucontext_t c;
makecontext(&c, (void (*)(void))f1, 1, 123); // ok
makecontext(&c, reinterpret_cast<void (*)(void)>(f1), 1, 123); // ok
auto f2 = [](int i){};
makecontext(&c, (void (*)(void))f2, 1, 123); // error
makecontext(&c, reinterpret_cast<void (*) (void)>(f2), 1, 123); // error
return 0;
}
Let's say you have already declared
f2
as in your example, and want to use it now withmakecontext
. Rather than trying to cast it, usestd::bind
(found in the <functional> header) to produce an object which is callable like avoid(*)(void)
:The object
f3
is a function object which is callable without any arguments. The end result is thatf2
end up being called with 0 as its argument. If you would rather a different value be passed tof2
, you can specify it as the second argument tobind
.Edit
As several commenters have pointed out, this isn't applicable in your case, as
makecontext
requires an actual function pointer. So, for reference sake, I thought I would point out one caveat that you might run into (in case you don't already know this): using a lambda as a function pointer only works if you don't utilize closures. As soon as you close over variables, the lambda can no longer degenerate to a function pointer, as it can without a closure.You can use a wrapper function to wrap it. It works for every lambda. The idea behind it is that since you can not pass functor as function pointer, you can pass a wrapper function that calls the lambda function. Another trick part is that I need to pass pointer instead of the whole object, it is because makecontext can only accept int arguments.
[](int i){}
is a captureless lambda that has a singleint
parameter and returns nothing; it is thus implicitly convertible tovoid(*)(int)
: a pointer to a function that takes a singleint
and returns nothing.Assuming the
makecontext
function is capable of handling functions with different types (it appears from its documentation that it is, though the documentation is a bit vague), then you'll need to use two casts to use it with a lambda: one to cast the lambda to a function pointer, and one to cast the lambda to thevoid(*)()
type:This is all rather unsafe (casting between function pointer types isn't exactly the safest thing to be doing), so it would be best to wrap this sort of functionality into a utility library. You can wrap the
makecontext
function with a function template so that you can be sure that all of your uses of the function are type safe, and all of the unsafe code is encapsulated in one place.