C ++ lambda在捕获变量时具有不同的类型

时间:2019-12-26 00:07:03

标签: c++ lambda

我正在尝试返回一个lambda函数,该函数从其当前作用域捕获变量。当我不捕获变量时,lambda函数将返回并且可以毫无问题地执行:

#include <iostream>

typedef void(*VoidLambda)();

VoidLambda get() {
    VoidLambda vl = []() {
        std::cout << "hello" << std::endl;
    };
    return vl;
};

int main()
{
    get()(); //prints "hello" as expected
    return 0;
}

如果vl试图捕获变量,则编译器将不再编译它:

#include <iostream>

typedef void(*VoidLambda)();

VoidLambda get(const char* x) {
    VoidLambda vl = [x]() { //Error: no suitable conversion function from "lambda []void ()->void" to "VoidLambda" exists
        std::cout << x << std::endl;
    };
    return vl;
};

int main()
{
    get("hello")();
    return 0;
}

我已经尝试过将第二个lambda转换为VoidLambda,但是问题仍然存在。

我想知道第一个和第二个lambda表达式之间的区别是什么,以及如何解决该问题(即使用捕获功能返回lambda函数)。

1 个答案:

答案 0 :(得分:7)

不捕获任何状态的Lambda函数是无状态的。因此,可以将它们建模为正态函数。如果他们需要捕获不再是真的状态:状态需要到某个地方并且函数指针没有该状态的位置。

基本上有两种选择:

  1. 使用推导类型返回lambda函数,例如:

    auto get(char* x) { return [x]{ std::cout << x << "\n";  }; }
    
  2. 返回lambda函数的类型擦除表示形式:

    std::function<void()> get(char* x) { return [x]{ std::cout << x << "\n"; }; }
    

根据您的需求选择哪种。第二个在概念上更接近函数指针。第一个效率更高,但要求该功能为inline(或至少在使用时可见)。