2013-01-11 48 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

相關問題