通用lambda如何在C++ 14中工作?

sas*_*hka 108 c++ lambda auto c++14

auto在C++ 14标准中,通用lambda如何工作(关键字作为参数类型)?

它是基于C++模板的,每个不同的参数类型编译器生成一个具有相同主体但替换类型(编译时多态)的新函数,还是更类似于Java的泛型(类型擦除)?

代码示例:

auto glambda = [](auto a) { return a; };
Run Code Online (Sandbox Code Playgroud)

And*_*owl 126

通用lambda被引入C++14.

简单地说,由lambda表达式定义的闭包类型将具有模板化的调用操作符,而不是lambda 的常规非模板调用操作符C++11(当然,auto在参数列表中至少出现一次).

你的榜样如此:

auto glambda = [] (auto a) { return a; };
Run Code Online (Sandbox Code Playgroud)

将创建glambda此类型的实例:

class /* unnamed */
{
public:
    template<typename T>
    T operator () (T a) const { return a; }
};
Run Code Online (Sandbox Code Playgroud)

C++ 14标准草案n3690的第5.1.2/5段规定了如何定义给定lambda表达式的闭包类型的调用运算符:

非泛型lambda表达式的闭包类型有一个公共内联函数调用操作符(13.5.4),其参数和返回类型分别由lambda-expression的parameter-declaration-clause和trailing-return-type描述.对于通用lambda,闭包类型有一个公共内联函数调用操作符成员模板(14.5.2),其template-parameter-list包含一个发明的类型模板参数,用于lambda的parameter-declaration-clause中每次出现的auto,按出场顺序.如果相应的参数声明声明了函数参数包(8.3.5),则本发明的类型模板参数是参数包.函数调用操作符模板的返回类型和函数参数是从lambda-expression的trailing-return-type和parameter-declarationclause派生的,它通过将parameter-declaration-clause的decl-specifiers中每次出现的auto替换为name-name相应发明的模板参数.

最后:

它是否类似于模板,其中每个不同的参数类型编译器生成具有相同主体但更改类型的函数或者它是否更类似于Java的泛型?

正如上面的段落解释的那样,泛型lambda只是具有模板化调用操作符的唯一,未命名的函子的语法糖.那应该回答你的问题:)

  • 但是,它们还允许使用模板方法在本地定义的类.这是新的. (7认同)
  • @Yakk:功能本地模板的限制是不是已经完全放弃了C++ 11? (2认同)
  • @phresnel:不,这个限制还没有解除 (2认同)
  • @AndyProwl:我意识到我的错误。确实被提升的是使用本地类型作为模板参数(如 `int main () { struct X {}; std::vector&lt;X&gt; x; }`) (2认同)

Seb*_*ach 25

不幸的是,它们不是C++ 11(http://ideone.com/NsqYuq)的一部分:

auto glambda = [](auto a) { return a; };

int main() {}
Run Code Online (Sandbox Code Playgroud)

使用g ++ 4.7:

prog.cpp:1:24: error: parameter declared ‘auto’
...
Run Code Online (Sandbox Code Playgroud)

但是,根据波特兰提出的通用lambdas提议,它可能在C++ 14中实现:

[](const& x, & y){ return x + y; }
Run Code Online (Sandbox Code Playgroud)

这通常会创建一个匿名的仿函数类,但是由于缺少类型,编译器会发出一个模板化的成员 - operator():

struct anonymous
{
    template <typename T, typename U>
    auto operator()(T const& x, U& y) const -> decltype(x+y)
    { return x + y; }
};
Run Code Online (Sandbox Code Playgroud)

或者根据通用(多态)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;
Run Code Online (Sandbox Code Playgroud)

所以是的,对于参数的每个排列,都会出现一个新的实例化,然而,该仿函数的成员仍然会被共享(即捕获的参数).

  • 允许删除_type-specifier_的提议完全是怪诞的. (6认同)

Cas*_*eri 15

这是一个与模板类似(甚至不等同于)的C++ 14特性(不是在C++ 11中).例如,N3559提供了这个例子:

例如,这个包含语句的通用lambda表达式:

auto L = [](const auto& x, auto& y){ return x + y; };
Run Code Online (Sandbox Code Playgroud)

可能会导致创建一个闭包类型,并且该对象的行为类似于下面的结构:

struct /* anonymous */
{
    template <typename T, typename U>
    auto operator()(const T& x, U& y) const // N3386 Return type deduction
    { return x + y; }
} L;
Run Code Online (Sandbox Code Playgroud)