【问题标题】:Signature difference between lambda with/without captured variable?带有/不带有捕获变量的lambda之间的签名差异?
【发布时间】:2011-08-26 21:38:38
【问题描述】:

我现在正在使用 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 版本在 Windows 上为“gcc (XvidVideo.RU - GCC 4.6.1 i686-pc-mingw32) 4.6.1 20110625 (prerelease)”。

为什么会有所不同?

【问题讨论】:

  • 我正在用 Visual Studio 2010 编译器尝试同样的事情,它不喜欢任何一种形式的 lambda...有谁知道这是否是 VS2010 impl 中的一个已知错误?

标签: lambda c++11


【解决方案1】:

只有无捕获的 lambda 可以转换为函数指针,并且根据编译器诊断,您的 sqlite3_exec 需要这样的指针 int (*)(void*, int, char**, char**)

引用§5.1.2[expr.prim.lambda]/6

没有 lambda 捕获的 lambda 表达式的闭包类型具有一个公共的非虚拟非显式 const 转换函数,该函数指向函数的指针,该函数具有与闭包类型的函数调用运算符相同的参数和返回类型。

【讨论】:

  • 有道理。只是想知道我是否可以以任何方式使用捕获的变量来解决这个问题。 (在这种特殊情况下,我当然可以使用 sqlite 的回调变量。)
  • @AndiDog 我猜你不得不为 C 库采取这么多 C++ 回调的方式:一个非成员或静态成员函数,它根据一些 @987654323 计算出真正调用的内容@.
  • 是的,sqlite3_exec 允许我将 void* 传递给回调,我只是天真地认为这可以使用 C++11 更轻松地完成。
【解决方案2】:

如果使用第一个参数进行回调呢?

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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-24
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 2011-08-18
    相关资源
    最近更新 更多