我在C++ 11项目中使用C库,这个C库提供了一个需要函数指针的函数.除非我捕获变量,否则我想将C++ 11 lambda传递给它,它正常工作.这是一个简短的例子:
#include <cstdio>
#include <functional>
typedef int (*Callback)();
void legacy(Callback callback) {
printf("%i\n", callback());
}
int stdCallback() {
return 1;
}
int main(int argc, char* argv[]) {
int number = 3;
// Standard C callback works
legacy(stdCallback);
// Lambda without capturing works
legacy([]() { return 2; });
// Lambda with capturing doesn't work
legacy([&]() { return number; });
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GNU C++编译器在第三次调用legacy函数时给出了以下错误消息:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:24:36: error: cannot convert ‘main(int, char**)::<lambda()>’ to ‘Callback {aka int (*)()}’ for argument ‘1’ to ‘void legacy(Callback)’
legacy([&]() { return number; });
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个问题?或者技术上不可能使用捕获lambda作为C函数指针?
不,如果它捕获任何东西,你就无法将lamdba转换为函数指针.
C++标准,第5.1.2/6节:[expr.prim.lambda],强调我的:
对于一个非通用λ-表达的闭合类型没有λ-捕获具有公共非虚拟非显式const的转换功能,以函数指针与C++语言联动装置(7.5),其具有相同的参数和返回类型为闭包类型的函数调用操作符.此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果
小智 5
函数指针就是:指向某些代码位的指针.没有数据.
具有捕获的lambda还需要捕获的数据以便提供有用的结果.
没有办法可以自动运作.但是,根据回调函数的调用方式,您可以解决它.您的legacy函数不会在任何地方保存回调,它只在自己执行期间调用它.此外,您没有使用线程或类似的东西.只要这些假设成立,您就可以解决这个问题:
#include <cstdio>
#include <functional>
typedef int (*Callback)();
void legacy(Callback callback) {
printf("%i\n", callback());
}
// Declared as void * outside legacyWrapper, instead of T * inside legacyWrapper,
// because no more than one variable is needed, no matter how many instantiations of
// legacyWrapper there are.
static void *legacyWrapperCallback;
template <typename T>
void legacyWrapper(T callback) {
legacyWrapperCallback = &callback;
legacy([]() -> int { return (*static_cast<T *>(legacyWrapperCallback))(); });
}
int stdCallback() {
return 1;
}
int main(int argc, char* argv[]) {
int number = 3;
// Standard C callback works
legacy(stdCallback);
// Lambda without capturing works
legacy([]() { return 2; });
// Lambda with capturing doesn't work...
//legacy([&]() { return number; });
// ...unless the C++ wrapper is used
legacyWrapper([&]() { return number; });
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
477 次 |
| 最近记录: |