我现在正在使用C ++ 11,并发现使用lambda作为sqlite回调的以下问题。在lambda中捕获向量变量时,我收到一条错误,指出签名不匹配。如果不在lambda中使用该变量([]
而不是[&ret]
,而不在内部使用ret
),它就可以正常工作。
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);
这是我得到的错误:
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版本是“gcc(XvidVideo.RU - GCC 4.6.1 i686-pc-mingw32)4.6.1 20110625(预发行版)”在Windows上。
为什么这会有所不同?
答案 0 :(得分:6)
只有无捕获的lambda可以转换为指向函数的指针,并且,基于编译器诊断,您的sqlite3_exec
需要这样的指针,int (*)(void*, int, char**, char**)
。
引用§5.1.2[expr.prim.lambda] / 6
没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,指向函数,该函数具有与闭包类型的函数调用操作符相同的参数和返回类型。
答案 1 :(得分:1)
使用第一个参数进行回调怎么样?
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);