Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signature difference between lambda with/without captured variable?

Tags:

c++11

lambda

I'm playing around with C++11 right now and found the following problem with using a lambda as callback to sqlite. When capturing a vector variable inside the lambda, I get an error saying that the signatures don't match. Without using that variable in the lambda ([] instead of [&ret], and not using ret inside), it works fine.

vector<SomeClass> ret;
char *err = nullptr;
int res = sqlite3_exec(db,
                       "some sql query, doesn't matter",
                       [&ret](void *unused, int argc, char **argv, char **columnName) -> int
                       {
                           ret.push_back(SomeClass());
                           return 0;
                       },
                       nullptr,
                       &err);

This is the error I get:

cannot convert 'TestClass::testMethod()::<lambda(void*, int, char**, char**)>' to 'int (*)(void*, int, char**, char**)' for argument '3' to 'int sqlite3_exec(sqlite3*, const char*, int (*)(void*, int, char**, char**), void*, char**)'

GCC version is "gcc (XvidVideo.RU - GCC 4.6.1 i686-pc-mingw32) 4.6.1 20110625 (prerelease)" on Windows.

Why does this make a difference?

like image 396
AndiDog Avatar asked Aug 26 '11 21:08

AndiDog


2 Answers

Only captureless lambdas can be converted to pointers to function, and, based on the compiler diagnostic, your sqlite3_exec expects such a pointer, int (*)(void*, int, char**, char**).

To quote §5.1.2[expr.prim.lambda]/6

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator.

like image 182
Cubbi Avatar answered Nov 08 '22 23:11

Cubbi


what about using the 1st argument for callback?

vector<SomeClass> ret;
char *err = nullptr;
int res = sqlite3_exec(db,
                       "some sql query, doesn't matter",
                       [](void *ctx, int argc, char **argv, char **columnName) -> int
                       {
                           static_cast<vector<SomeClass>*>(ctx)->push_back(SomeClass());
                           return 0;
                       },
                       &ret,
                       &err);
like image 29
pepero Avatar answered Nov 08 '22 23:11

pepero