2013-01-11 3 views
22

Czy ktoś wie, czy następujące niejawna wychwytywanie „TS” jest dobrze wykształcona:Czy pakiet parametrów może być przechwytywany niejawnie w ramach lambd C++ 11?

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

Czy średnia jasno stwierdzić, że nigdzie nie powinno być dobrze uformowane?

+0

Wiem, że możesz je przechwycić jawnie, ale nie widziałem niczego, co mogłoby skutkować "czymkolwiek możesz przechwycić jawnie, możesz przechwycić niejawnie i na odwrót". – chris

+0

Jeśli jest dobrze uformowany, wierzę, że spowoduje nieskończoną rekurencję. :-) Nie jestem pewien, co standard mówi o tym. Spodziewam się nieokreślonego zachowania. ;-) Jeśli tak, to znaczy, że parsowanie tego kodu może mieć jakikolwiek rezultat, nawet jeśli wyrażenie paczka wewnątrz lambda jest dobrze uformowane. :-) – Omnifarious

+0

dzięki omburarious - naprawiłem nieskończony problem rekursji. –

Odpowiedz

12

14.5.3/6:

konkretyzacją z dodatku, który nie jest wyrazem sizeof... tworzy listę E1, E2, ..., EN, gdzie N to liczba elementów w parametry rozszerzenia paczki. Każda Ei jest generowana przez utworzenie wystąpienia wzorca i zastąpienie każdego parametru rozwijania paczki przez jego element i. Wszystkie Ei stają się elementami na liście zamykającej.

Niezależnie od tego, czy masz prawo do wyraźnie przechwycić paczkę (możesz, używając [ts ...]), ogólna zasada ekspansji spowoduje zdobyciu każdego elementu listy.

+0

Dobra droga do tego. – chris

+2

lub '[& ts ...]'. Również ten akapit mówi o regułach rozszerzania paczek, ale nie stwierdził niczego przydatnego w przechwytywaniu reguł pakowania parametrów ... IMHO, nie odpowiada na pytanie. –

7

myślę, że to dobrze uformowane, nie znalazłem prosty oświadczenie (sformułowanie czasami brakuje w jasności/ilustracji dla niektórych sytuacjach), ale myślę, że można wywnioskować:

§5.1.2/23 :

przechwytywanie następnie przez elipsy jest Dodatek (14.5.3). [Przykład:

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

- przykład end]

  • Przechwytywanie następnie przez elipsy implikuje args w lambda wychwytu jest przykładem przechwytywanie (w tym przypadku jawne), a godnym uwagi faktem jest to, że args jest paczką parametrów identyfikator. Ten krótki akapit ma wyłącznie za zadanie opisanie, jak przechwytywania lambda zatrzymuje się, co pokazuje, że pakiety parametrów mogą być przechwytywane, nawet jeśli ich celem nie jest , pozwalając im na przechwycenie do .

§5.1.2/12.

jednostka zostaje schwytany jeśli to jest zrobione wyraźnie lub dorozumiany [...]

§3/3:

jednostka jest wartość Przedmiotem odniesienie, funkcja wyliczający, typ członkiem klasy, szablon, szablon specjalizacji, nazw, parametr opakowanie, lub to.

Od tego zakładam parametrów paczki są podmioty, które mogą być uchwycone jawnie lub niejawnie, a więc stosuje się takie same zasady jak w przypadku zmiennych Chwytając zwykłych, z wyjątkiem, że opakowania parametrów zostanie odpowiednio rozszerzona.

Domyślam się, że twoje pytanie (i ta sama argumentacja) może być równie dobrze zastosowane do zmiennych referencyjnych, na przykład (It is unspecified whether or not a reference requires storage. §8.3.2/4). Wygląda na to, że jesteś zainteresowany, kiedy masz pozwolenie na odwołanie się do zestawu parametrów o identyfikatorze wewnątrz lambda.

Możesz myśleć tak samo o zmiennych referencyjnych w zakresie zewnętrznym, ponieważ możesz mieć do nich dostęp, ale nie możesz nawet uzyskać dostępu do identyfikatora oryginalnej zmiennej.

Są tak eteryczne jak paczki parametrów.

+0

* capture * to konstrukcja gramatyczna zdefiniowana na początku zdania: * capture *: * identifier * | '&' * identyfikator * | 'ten'. W standardzie jest kilka ogólnych terminów ... a elipsa musi znaleźć się gdzieś w gramatyce. Chociaż niejawne przechwytywanie zmiennej wymaga nazwania jej za pomocą identyfikatora, nie oznacza to, że takie podwyrażenia tworzą * przechwytywanie *. Ponadto produkcja * capture * nie jest zgodna z rozszerzeniem na większym wyrażeniu, takim jak 'std :: forward (o) ...', więc 5.1.2/12 nie może być zastosowany. – Potatoswatter

+0

@Potatoswatter, nie dostałem tego, co próbujesz wskazać, przepraszam. Podkreśliłem 5.1.2/12 tylko po to, aby wymusić, że chociaż standard dzieli przechwyty w dwóch rodzajach, te dwa wciąż mogą być odniesione jako przechwyty w szerszym znaczeniu, a więc 5.1.2/23 jest o obu, a nie jednym specjalnie. Ponadto pakiet parametrów może być odwołany tylko przez identyfikator, więc nie widzę problemu z tą klauzulą. –

+0

Terminy pisane kursywą odnoszą się tylko do konstrukcji gramatycznych. "* Capture *" to coś innego niż "schwytany byt", nie ma miejsca na sędziowanie. Przepraszam, miałem na myśli 5.1.2/23 nie można zastosować, nie 5.1.2/12. – Potatoswatter