Signature difference between lambda with / without captured variable?

I am playing with C ++ 11 right now and have discovered the following problem using lambda as a callback to sqlite. When capturing a vector variable inside lambda, I get an error that the signatures do not match. Not using this variable in 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**)' 

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

Why does it matter?

+6
source share
2 answers

Only captured lambdas can be converted to pointers in order to function, and based on compiler diagnostics, 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 without lambda capture has a public non-virtual implicit conversion function const for a pointer to a function that has the same parameter and return types as the closure function call statement.

+6
source

how about using 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); 
+1
source

Source: https://habr.com/ru/post/896010/


All Articles