首页 > 解决方案 > C++14 通用 lambda 捕获的 C++11 仿真与可变说明符之间的关系

问题描述

在 Effective Modern C++ 第 32 条的第 227-228 页,Scott Meyers 提出了以下代码块,作为解决C++11 中缺乏通用 lambda 捕获的一种方法。

// data is in scope
auto func =
  std::bind(
      [](const std::vector<double>& x) // I've renamed it x so there's no ambiguity in my description below
      { /* usses of x */ },
      std::move(data)
  );

然后他发表了以下评论,我总体上不太了解。

默认情况下,operator()从 lambda 生成的闭包类中的成员函数是const. const这具有在 lambda 主体内呈现闭包中的所有数据成员的效果。data但是,绑定对象内部的移动构造副本不是const,因此为了防止该副本data在 lambda 内部被修改,将 lambda 的参数声明为 reference-to- const。如果 lambda 被声明mutable,则operator()在其闭包类中不会被声明const,并且const在 lambda 的参数声明中省略是合适的:

// data is in scope
auto func =
  std::bind(
    [](std::vector<doubld>& x) mutable // ditto
    { /* uses of x */ },
    std::move(data)
  );

我试图打破它:

(然而,那个 lambda 首先没有捕获任何东西,所以以下几点似乎与我无关......)

所以,如果声明了 lambda [...],我不明白最后一个时期的意义。

标签: c++11lambdac++14

解决方案


好的,写这个问题帮助我理解我只是忽略了该代码的最初动机:模拟广义 lambda 捕获。

也许 Scott Meyers 还暗示,该代码的编写者很自然地希望绑定对象func的行为类似于所需的 lambda ,因为它使用与存储在其中的实际 lambdafunc相同的说明符进行编码(实际上文本仅指说明mutable符,可能是因为这是唯一值得讨论的)。

换句话说,

  • 看到通过mutable存储在内部的非lambda ,程序员可能期望它将表现为相应的非C++14 lambda,因此实际 lambda 的参数存储在;funcstd::bindfuncmutableconstfunc
  • 如果实际的 lambda 是mutable,那么用户希望func表现得像对应的mutableC++14 lambda,所以他不希望它保留未修改的捕获值,因此const在第二块代码中缺少。

更短:

存储在其中的非mutablelambdafunc不应修改其参数,因为相应的所需非mutableC++14 lambda 不会修改其捕获的变量


推荐阅读