2013-01-11 50 views
22

有谁知道“TS”的下面隐含捕捉合式:参数包是否可以在C++ 11 lambdas中隐式捕获?

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); 

是否标准明确任何地方指出,这不应该被很好地形成?

+0

我知道你可以明确地捕获它们,但是我还没有看到任何“无论你明确捕获,你都可以隐式捕获,反之亦然”的效果。 – chris

+0

如果它形成良好,我相信它会导致无限递归。 :-)我不确定这个标准是怎么说的。我认为这是未定义的行为。 ;-)如果是这样,那就意味着解析该代码可以得到任何结果,即使lambda中的包装表达式格式良好。 :-) – Omnifarious

+0

谢谢omnifarious - 我修复了无限递归问题。 –

回答

12

14.5.3/6:

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

不管你被允许明确捕获包(可以使用[ts ...]),扩张的一般规律将导致列表中的每个元素的捕捉。

+0

好的方法去它。 – chris

+2

或'[&ts ...]'。此外,这一段讲述包扩展规则,但没有说明有关参数包捕获规则的任何帮助......恕我直言,它不回答这个问题。 –

7

我想这是良好的,我还没有找到一个直接声明(措辞有时清晰度/插图某些情况下没有),但我想这可以推断:

§5.1.2/ 23 :

A捕获随后省略号是一包扩展(14.5.3)。 [实施例:

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

- 端示例]

  • A捕获后跟省略,意味着args,在λ-捕获,是一个例子一个捕获(在这种情况下,明确的),并且值得注意的事实是args是一个参数包标识符。这个短小段落描述lambda-captures如何保持包扩展,这表明参数包可以被捕获,即使其目的不是约允许他们被捕获

§5.1.2/ 12:

实体被捕获如果它被捕获明确隐含 [...]

§3/ 3:

一种实体是值,对象,参考,功能,枚举,类型,类的成员,模板,模板特,命名空间,参数包,或这。

从这我假设参数包是可以明确或隐含被捕获,因此,同样的拍摄规则对于普通的变量应适用,但参数包应相应扩大实体。

我想你的问题(和相同的论证)同样适用于例如参考变量(It is unspecified whether or not a reference requires storage. §8.3.2/4)。当你允许或不参考参数包标识符时,你似乎对你感兴趣。

您可以认为外部作用域中的引用变量相同,因为您可能有权访问它们,但甚至不能访问原始变量的标识符。

它们与参数包相同。

+0

* capture *是在子句开头定义的语法结构:* capture *:* identifier * | '&'*标识符* | 'this'。在标准中这样的一般术语很少......并且省略号需要在语法中的某处。尽管隐式地捕获变量涉及用标识符命名它,但并不意味着这样的子表达形成* capture *。此外,* capture *制作与'std :: forward (o)...'等较大表达式的扩展不匹配,因此,5.1.2/12无法应用。 – Potatoswatter

+0

@Patatoswatter,我没有得到你想指出的,抱歉。我强调5.1.2/12只是为了强制这一点,即使标准分歧有两种捕捉方式,但这两种方法仍然可以作为更广泛意义上的捕捉参考,所以5.1.2/23是关于两者的,而不是一个特别。此外,参数包只能由标识符引用,所以我没有看到该子句的问题。 –

+0

斜体术语仅指语法结构。 “*捕获*”与“被捕获的实体”不同,“没有裁判的余地。对不起,我的意思是5.1.2/23不能申请,而不是5.1.2/12。 – Potatoswatter

相关问题