C++ 11 lambdas到函数指针

Rap*_*sso 10 c++ c++11

我开始使用C++ 11 lambdas开发应用程序,并且需要将某些类型转换为函数指针.这在GCC 4.6.0中完美运行:

void (* test)() = []()
{
    puts("Test!");
};

test();
Run Code Online (Sandbox Code Playgroud)

我的问题是当我需要在lambda中使用函数或方法局部变量时:

const char * text = "test!";

void (* test)() = [&]()
{
    puts(text);
};

test();
Run Code Online (Sandbox Code Playgroud)

G ++ 4.6.0给出了强制转换错误代码:

main.cpp: In function 'void init(int)':
main.cpp:10:2: error: cannot convert 'main(int argc, char ** argv)::<lambda()>' to 'void (*)()' in initialization
Run Code Online (Sandbox Code Playgroud)

如果使用auto,它可以正常工作:

const char * text = "Test!";

auto test = [&]()
{
    puts(text);
};

test();
Run Code Online (Sandbox Code Playgroud)

我的问题是:如何用[&]为lambda创建一个类型?在我的情况下,我不能使用STL std :: function(因为我的程序不使用C++ RTTI和EXCEPTIONS运行时),并且它有一个简单的函数实现来解决这个问题?

Nic*_*las 10

我不能使用STL std :: function(因为我的程序不使用C++ RTTI和EXCEPTIONS运行时)

那么你可能需要编写自己的等价物std::function.

类型擦除的通常实现std::function不需要RTTI来实现其大多数功能; 它通过常规虚函数调用工作.所以编写自己的版本是可行的.

事实上,唯一的东西std::function需要 RTTI是target_typetarget功能,这是不是世界上最有用的功能.您可以在std::function不调用这些函数的情况下使用,假设您正在使用的实现不需要RTTI用于其常规业务.

通常,当您禁用异常处理时,程序只会在遇到throw语句时关闭并出错.而且,由于大多数std::function发出的异常都不是你能够从中恢复的东西(调用空的function,内存耗尽等),你可能只是std::function按原样使用.


Dav*_*eas 9

只有没有捕获的lambda才能转换为函数指针.这是lambdas的扩展,仅适用于这种特殊情况[*].通常,lambdas是函数对象,您无法将函数对象转换为函数.

具有状态(捕获)的lambda的替代方法是使用std::function而不是普通函数指针.


[*]:如果保持状态的lambda可以转换为函数指针,那么状态会保持在哪里?(注意,这个特殊lambda可能有多个实例,每个实例都有自己需要单独维护的状态)


bam*_*s53 6

如前所述,只有捕获任何内容的lambda才能转换为函数指针.

如果你不想使用或写一些类似std :: function的东西,那么另一种选择是将你原本捕获的东西作为参数传递.您甚至可以创建一个结构来保存它们.

#include <iostream>

struct captures { int x; };
int (*func)(captures *c) = [](captures *c){ return c->x; };

int main() {
    captures c = {10};

    std::cout << func(&c) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用不需要捕获的global/static/thread_local/constexpr变量.