泛型lambda在C++14中是如何工作的
How does generic lambda work in C++14?
泛型lambda在C++14标准中是如何工作的(auto
关键字作为参数类型)?
它是基于C++模板的,对于每个不同的参数类型,编译器都会生成一个具有相同主体但被替换的类型的新函数(编译时多态性),还是更类似于Java的泛型(类型擦除)?
代码示例:
auto glambda = [](auto a) { return a; };
泛型lambda是在C++14
中引入的。
简单地说,lambda表达式定义的闭包类型将具有模板化调用运算符,而不是C++11
的lambdas的常规非模板调用运算符(当然,当auto
在参数列表中至少出现一次时)。
所以你的例子:
auto glambda = [] (auto a) { return a; };
将使glambda
成为这种类型的实例:
class /* unnamed */
{
public:
template<typename T>
T operator () (T a) const { return a; }
};
C++14标准草案n3690第5.1.2/5段规定了如何定义给定lambda表达式的闭包类型的调用运算符:
非泛型lambda表达式的闭包类型具有公共内联函数调用运算符(13.5.4)其参数和返回类型由lambda表达式的参数声明子句描述和拖尾返回类型对于泛型lambda,闭包类型具有公共内联函数调用操作员成员模板(14.5.2),其模板参数列表由一个发明的类型模板参数组成对于lambda的参数声明子句中每次出现auto,按出现顺序。如果相应的参数声明声明函数参数包(8.3.5)。函数调用的返回类型和函数参数运算符模板派生自lambda表达式的尾部返回类型和参数声明子句通过将参数声明子句的decl说明符中每次出现的auto替换为相应发明的模板参数的名称。
最后:
它类似于模板吗?在模板中,编译器为每个不同的参数类型生成具有相同主体但更改了类型的函数,还是更类似于Java的泛型?
正如上面的段落所解释的,泛型lambda只是具有模板化调用运算符的唯一、未命名函子的语法糖。这应该可以回答您的问题:)
不幸的是,它们不是C++11的一部分(http://ideone.com/NsqYuq):
auto glambda = [](auto a) { return a; };
int main() {}
使用g++4.7:
prog.cpp:1:24: error: parameter declared ‘auto’
...
然而,它可能在C++14中实现的方式是根据通用lambdas的Portland提案:
[](const& x, & y){ return x + y; }
这将在很大程度上产生通常创建的匿名函子类,但由于缺少类型,编译器将发出模板化成员operator()
:
struct anonymous
{
template <typename T, typename U>
auto operator()(T const& x, U& y) const -> decltype(x+y)
{ return x + y; }
};
或者根据新的提议通用(多态)Lambda表达式的提议
auto L = [](const auto& x, auto& y){ return x + y; };
--->
struct /* anonymous */
{
template <typename T, typename U>
auto operator()(const T& x, U& y) const // N3386 Return type deduction
{ return x + y; }
} L;
因此,是的,对于参数的每一个排列,都会出现一个新的实例化,然而,该函子的成员仍然是共享的(即捕获的参数)。
这是一个建议的C++14特性(不在C++11中),与模板类似(甚至等效)。例如,N3559提供了以下示例:
例如,这个包含语句的泛型lambda表达式:
auto L = [](const auto& x, auto& y){ return x + y; };
可能导致创建一个闭包类型和行为类似于下面结构的对象:
struct /* anonymous */ { template <typename T, typename U> auto operator()(const T& x, U& y) const // N3386 Return type deduction { return x + y; } } L;
摘自《C++模板:完整指南》(第2版)第5.5.2节。
5.5.2通用Lambdas和成员模板
注意,C++14中引入的通用lambda是成员模板的快捷方式。一个简单的lambda计算任意类型的两个参数的"answers":
[] (auto x, auto y) {
return x + y;
}
是以下类的默认构造对象的快捷方式:
class SomeCompilerSpecificName {
public:
SomeCompilerSpecificName(); // constructor only callable by compiler
template<typename T1, typename T2>
auto operator() (T1 x, T2 y) const {
return x + y;
}
};
这意味着对于泛型lambda,编译器正在生成一个模板化类。因此,对于auto
,模板的类型推导规则将适用。
一个有趣的推论是,您可以从lambdas继承。
关于从lambdas继承的更多信息:
- C++周刊-Ep 40-从Lambdas继承
- 从lambda继承意味着什么
- 代码示例
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?
- sdl软件渲染器不工作,工作在硬件加速的一个