Frage

C++11 lambdas that does not capture anything can be stored in a function pointer. One just need to ensure that lambda accepts and returns the same parameters as the function pointer.

In GObject library all callbacks has type void(*GCallback) (void). This definition does not anyhow affect signature of the callback though:

The type used for callback functions in structure definitions and function signatures. This doesn't mean that all callback functions must take no parameters and return void. The required signature of a callback function is determined by the context in which is used (e.g. the signal to which it is connected). Use G_CALLBACK() to cast the callback function to a GCallback.

In other words, one can pass function like this:

int my_function(int a, char b) {}

by casting its type (that's what G_CALLBACK do):

do_something(G_CALLBACK(my_function));

Unfortunately typecasting does not work with C++11 lambdas:

do_something(G_CALLBACK([](int a, char b) -> int {...});
// Cannot cast from type lambda to pointer type GCallback

Is it possible to use C++ lambdas of arbitrary type in place of GCallback?

UPDATE

Just to clarify, I know that lambda can be casted to a function pointer if their signatures match. My question is in another dimension.

The ISO C standard guarantees that function can be casted forth and back without loosing any precision. In other words one the following expression is valid:

int f(int a){...}

void (*void_f)() = (void (*)())f;
int (*restored_f)(int) = (int (*)(int))void_f;
restored_f(10);

My question is whether the following expression is also valid according to C++11:

int (*f)(int) = [](int a) -> int {};
void (*void_f)() = (void (*)())f;
int (*restored_f)(int) = (int (*)(int))void_f;
restored_f(10);
War es hilfreich?

Lösung

Lambdas without a capture are implicitly convertible to a pointer to a function by the standard. Though not all compilers support this feature at the moment (https://stackoverflow.com/a/2935230/261217).

Then you can explicitly cast a function pointer to GCallback.

Andere Tipps

The following code compiles and works for me (MSVC 2013):

auto lambdaFunc = [](int a, char b) -> int { return 0; };

typedef int (*LambdaType)(int, char);

GCallback fnTest1 = G_CALLBACK((LambdaType)lambdaFunc);
GCallback fnTest2 = G_CALLBACK((LambdaType) [](int a, char b) -> int { return 0; });

do_something(fnTest1);
do_something(fnTest2);
do_something(G_CALLBACK((LambdaType)lambdaFunc));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top