【问题标题】:When is a lambda trivial?什么时候 lambda 微不足道?
【发布时间】:2016-01-04 07:53:12
【问题描述】:

什么时候 lambda a 可以保证是微不足道的,如果有的话?

我假设如果它只捕获普通类型或什么都不捕获,那将是微不足道的。不过,我没有任何标准语言来支持这一点。

我的动机是将一些代码从 Visual C++ 12 移到 14 并发现一些静态断言在处理我认为微不足道的 lambda 时失败。

例子:

#include <type_traits>
#include <iostream>
using namespace std;

int main()
{
    auto lambda = [](){};

    cout << boolalpha << is_trivially_copyable<decltype(lambda)>{} << endl;
}

这会在 vs140 上产生 false,但在 vs120 和 clang 中会产生 true。由于周围没有 gcc >= 5,我无法测试 gcc。我希望这是 vs140 的回归,但我不确定这里的行为是否正确。

【问题讨论】:

  • gcc 5.2 也产生 true: Demo

标签: c++ c++11 lambda typetraits


【解决方案1】:

标准没有指定闭包类型(lambda 表达式的类型)是否是平凡的。它明确地将其留给实现,这使其不可移植。恐怕你不能依赖你的static_assert 产生任何一致的东西。

引用 C++14 (N4140) 5.1.2/3:

... 一个实现可以定义不同于下面描述的闭包类型,只要这不会改变 observable 程序的行为除了改变之外:

  • 闭包类型的大小和/或对齐方式,
  • 闭包类型是否可简单复制(第 9 条),
  • 闭包类型是否为标准布局类(第 9 条),或者
  • 闭包类型是否为 POD 类(第 9 条)。

...

(强调我的)

解析那句话中的双重否定后,我们可以看到允许实现来决定闭包类型是普通可复制、标准布局还是POD。

请注意,相同的措辞也出现在 C++17 (N4659) [expr.prim.lambda.closure] 8.1.5.1/2 中。

【讨论】:

  • 嗯,这对我来说非常难过:(我根本没想到会得到这个答案。我想我学到了关于不做假设的教训。
  • c++17 会改变吗?
【解决方案2】:

根据草案标准N45275.1.2/3 Lambda 表达式 [expr.prim.lambda]强调我的):

lambda 表达式的类型(也是 闭包对象)是一个唯一的、未命名的非联合类类型——称为 闭包类型——其属性如下所述。此类类型 既不是聚合(8.5.1)也不是文字类型(3.9)。关闭 type 在最小的块作用域、类作用域或 包含相应 lambda 表达式的命名空间范围。 [ 注意:这决定了一组命名空间和相关的类 使用闭包类型 (3.4.2)。 a的参数类型 lambdadeclarator 不会影响这些关联的命名空间和 类。 — end note ] 一个实现可以定义闭包类型 与下面描述的不同,前提是这不会改变 程序的可观察行为,而不是通过更改:

(3.1) — 闭包类型的大小和/或对齐方式,

(3.2) — 闭包类型是否可简单复制(第 9 条),

(3.3) — 是否 闭包类型是标准布局类(第 9 条),或者

(3.4) — 是否 闭包类型是 POD 类(第 9 条)。

一个实现应该 不要将右值引用类型的成员添加到闭包类型中

因此,它依赖于实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多