当前位置: 首页 > 知识库问答 >
问题:

泛型lambda在C 14中是如何工作的?

柯建业
2023-03-14

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

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

代码示例:

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

共有3个答案

鱼征
2023-03-14

这是一个拟议的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;
姚凯歌
2023-03-14

不幸的是,它们不是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’
...

然而,根据波特兰关于通用lambda的提案,它可能在C 14中实现的方式:

[](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;

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

经骁
2023-03-14

C 14中引入了通用lambda。

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

所以你的例子:

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的参数声明子句中的每次自动出现,按出现顺序排列。如果相应的参数声明声明了一个函数参数包,则发明的类型模板参数是一个参数包(8.3.5)。函数调用操作符模板的返回类型和函数参数来源于lambda表达式的尾随返回类型和参数声明子句,方法是用相应发明的模板参数的名称替换参数声明子句的decl-限定符中的每次自动出现。

最后:

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

如上所述,泛型lambda只是具有模板调用运算符的唯一未命名函子的语法糖。这应该可以回答你的问题:)

 类似资料:
  • 问题内容: 虽然我确实了解泛型的一些特殊情况,但以下示例缺少一些内容。 我有以下课程 第4行给我错误 显然,编译器认为差异实际上并不相等。虽然我的直觉告诉我,这是正确的。 谁能提供一个示例,如果第4行合法,我会遇到运行时错误? 编辑: 为避免混淆,我将第3行中的in 替换为一个具体的作业 问题答案: 正如肯尼(Kenny)在评论中指出的那样,您可以通过以下方法解决此问题: 这立即告诉我们,该操作并

  • 问题内容: 在查找(测试)信息时,我遇到了一些问题,完全不知道为什么会发生。现在,我知道没有实际的理由执行此操作,这绝对是可怕的代码,但是为什么行得通呢? 因此,基本上,我将对象添加到Quods的ArrayList中。现在,我看到java如何无法有效地检查它,因为它必须浏览所有引用,而这些引用可能甚至都没有存储在任何地方。但是为什么get()起作用了。get()是否不是要返回Quod的实例,就像在

  • 在Spark中是如何工作的? 如果我们注册一个对象作为一个表,会将所有数据保存在内存中吗?

  • 我从网上和论坛上看到了关于BatchSize的相关主题,但我仍然不明白一些部分。所以让我们描述一下我理解的和不理解的。 批量取数:选择取数的优化策略。Hibernate通过指定主键或外键列表,在一次选择中检索一批实体实例或集合。 让我们有JPA 2.0,带有Hibernate实现。这些实体: } 因此,我懒得去了解产品中的制造商。因此,当我执行select fetching时,就完成了。所以我有很

  • 我的项目中的三个模型对象(本文末尾的模型和存储库片段)之间确实存在关系。 当我调用时,它会触发三个select查询: (“sql”) (对我来说)那是相当不寻常的行为。在阅读Hibernate文档后,我认为它应该始终使用连接查询。当类中的更改为时,查询没有区别(使用附加选择进行查询),当更改为时,城市类的查询也一样(使用JOIN进行查询)。 当我使用抑制火灾时,有两种选择: 我的目标是在所有情况下

  • 我经常把文本输出到文件中。我想知道:是如何工作的? 当我调用时,它是否在文件上写入文本?如果它不写文本,我需要使用flush函数来写数据吗? 例如: 如果while循环中发生错误,文件将在不写入数据的情况下关闭。如果我在while循环中使用函数,那么为什么要使用?如果我错了,请纠正我。