可以在C ++ 11 lambdas中隐式捕获参数包吗?

时间:2013-01-11 02:57:20

标签: c++ c++11 lambda language-lawyer variadic-templates

有没有人知道以下隐含的'ts'捕获是否格式正确:

template<class ... Ts> void bar(Ts ... ts) { }

template<class ... Ts> int foo(Ts ... ts) {
    auto L = [=] () {
       bar(ts...);
    };
    L();
    return 0;
}
int g = foo(1, 2, 3);

标准是否清楚地说明了这个不应该形成的地方?

2 个答案:

答案 0 :(得分:12)

14.5.3 / 6:

  

不是sizeof...表达式的包扩展的实例化会生成列表E1,E2,...,EN,其中   N是包扩展参数中的元素数。通过实例化模式并用其第i个元素替换每个包扩展参数来生成每个Ei。所有的Ei都成为封闭列表中的元素。

无论您是否被允许明确捕获包(您可以使用[ts ...]),扩展的一般规则将导致捕获列表中的每个元素。

答案 1 :(得分:7)

我猜它形成得很好,我没有找到一个直接的陈述(对于某些情况,措辞有时缺乏清晰度/插图)但我想可能会推断:

<强>§5.1.2/ 23:

  

省略号后面的跟随是一个包扩展(14.5.3)。 [例如:

      template<class... Args>
      void f(Args... args) {
        auto lm = [&, args...] { return g(args...); };
        lm();
      }
  

- 结束示例]

  • lambda-capture 中捕获后跟省略号,隐含args,是捕获的示例(在本例中为显式) ,值得注意的事实是args是参数包标识符。这个简短的段落唯一的工作是描述 lambda-captures 如何保持包扩展,这表明参数包可以捕获,即使它的目的不是允许它们被捕获

<强>§5.1.2/ 12:

  

如果明确隐式捕获实体。[...]

<强>§3/ 3:

  

实体是值,对象,引用,函数,枚举器,类型,类成员,模板,模板特化,命名空间,参数包或此。< / p>

由此我假设参数包是可以显式或隐式捕获的实体,因此,应适用与普通变量相同的捕获规则,但参数包应相应扩展。 / p>

我猜你的问题(以及相同的论证)可以同样适用于参考变量,例如(It is unspecified whether or not a reference requires storage. §8.3.2/4)。当你被允许或不在lambda中引用参数包 identifier 时,你似乎感兴趣。

您可以对外部作用域中的引用变量进行相同的思考,因为您可以访问它们,但甚至无法访问原始变量的标识符。

它们与参数包一样空灵。