Signature difference between lambda with/without captured variable?
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 开发者_JAVA百科- GCC 4.6.1 i686-pc-mingw32) 4.6.1 20110625 (prerelease)" on Windows.
Why does this make a difference?
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.
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);
精彩评论