C++中Lambda的类型
Type of lambdas in C++
我试图用C++学习lambdas,但偶然发现了一些我不太理解的东西。
这是代码:
#include <iostream>
typedef double Func(double);
double applyFunc(Func f, double x)
{
return f(x);
}
int main()
{
std::cout << applyFunc([](double x) {return x + 1;}, 3) << std::endl;
}
现在,它工作得很好(打印"4"),即所使用的lambda表达式的类型正是double (*)(double)
。
但是如果我给lambda表达式添加闭包,比如:
int main()
{
int n = 5;
std::cout << applyFunc([n](double x) {return x + n;}, 3) << std::endl;
}
然后我从编译器那里得到一个错误:
In function ‘int main()’:
error: cannot convert ‘main()::__lambda0’ to ‘double (*)(double)’ for argument ‘1’ to ‘double applyFunc(double (*)(double), double)’
3) << std::endl;
^
我不明白为什么。我的意思是,从applyFunc()
的角度来看,它仍然接收一个指向接受double
参数并返回double
的函数的指针,而且它不知道我们使用了上下文中的变量"n",所以lambda表达式的类型应该与第一个示例中的相同,对吧?
我将非常感谢您的帮助,提前感谢您!
lambda只有在没有捕获的情况下才能转换为函数指针,我们可以通过标准草案5.1.2
lambda表达式来了解这一点,其中说(emphasis mine):
没有lambda捕获的lambda表达式的闭包类型具有public非虚拟非显式const到指针的转换函数函数具有与闭包相同的参数和返回类型类型的函数调用运算符。此转换返回的值函数应为调用时具有与调用闭包类型的函数调用操作符的效果相同。
这是一种不依赖于这种转换的替代解决方案:
template <typename Callable>
double applyFunc(Callable f, double x)
{
return f(x);
}
更新
如果您对使用std::function
和模板之间的区别感兴趣,那么您应该阅读std::function vs template。这里有很多好的答案,也有很多值得思考的地方。
每个lambda表达式都返回一个具有不同类型的对象。如果lambda表达式的没有捕获任何变量,则可以将其转换为适当签名的函数指针类型(即,返回类型和参数需要与lambda表达式一致)。当捕捉到变量时,创建的实体不能用普通函数表示。相反,lambda表达式生成一个具有函数调用运算符的类类型的对象。也就是说,您的第二个代码使用一个lambda表达式来生成一个类的对象,该对象大致相当于:
class lambda {
int n;
public:
lambda(int n): n(n) {}
double operator()(double x) const { return x + n; }
};
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 在 lambda 捕获中声明的变量的类型推导
- C++ 模板类型的静态 lambda 成员的构造
- Clang 工具,用于提取给定 lambda 类型的 lambda 主体
- 如果 lambda 没有指定的类型,std::function 如何接受 lambda?
- Lambda可以用作非类型模板参数吗
- 如何确定捕获不可复制参数的 lambda 的类型?
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- C++模板函数中,指定回调函子/lambda 的参数类型,同时仍允许内联?
- 运算符中的不同类型? 具有无捕获,相同的签名,lambda
- 通过参数传递 lambda(无函数类型模板)
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- 如何推导lambda的返回类型
- 尽管显式声明了返回类型,但对lambda的调用是不明确的
- 是否创建具有不同返回类型的lambda
- 防止 lambda 的返回类型扣除
- 在 lambda 函数 g++-4.8 中调用继承的受保护子类型
- 在 lambda 中从引用类型捕获的值的类型,不使用通用捕获
- 我可以让返回类型自动处理具有相同签名但捕获不同内容的 lambda 吗?
- 复制分配C++相同类型的 lambda