2016-08-03 41 views
4

Ich kann ein Beispiel aus C++ 14 Standardentwurf N4140 5.1.2.12 [expr.prim.lambda] nicht ganz verstehen.Verwendung der nicht erfassten Variable in Lambda

Ein lambda-Ausdruck mit einem zugeordneten capture-default, die nicht explizit diese oder eine Variable mit automatischer Speicherdauer nicht erfassen (dies schließt jegliche ID-Ausdruck, der damit verbundenen nicht-statischen Daten zu einem initcapture die Bezug zu nehmen gefunden wurde Mitglied), gesagt wird, implizit die Einheit zu erfassen (dh diese oder eine Variable), wenn die Verbindung-Anweisung:

  • odr-nutzt das Unternehmen oder
  • das Unternehmen in einem potentiell bewerteten Ausdruck Namen in dem Der einschließende vollständige Ausdruck hängt von einem generischen Lambda-Parameter ab, der innerhalb des reichenden Bereichs von l deklariert wird Ambda-Ausdruck.

[Beispiel:

void f(int, const int (&)[2] = {}) { } // #1 
void f(const int&, const int (&)[1]) { } // #2 
void test() { 
    const int x = 17; 
    auto g = [](auto a) { 
    f(x); // OK: calls #1, does not capture x 
    }; 
    auto g2 = [=](auto a) { 
    int selector[sizeof(a) == 1 ? 1 : 2]{}; 
    f(x, selector); // OK: is a dependent expression, so captures x 
    }; 
} 

-Ende Beispiel]

Alle diese implizit erfassten Einheiten werden im Erreichen Umfang der Lambda-Ausdruck deklariert werden.

[Hinweis: Die implizite Erfassung einer Entität durch einen verschachtelten Lambda-Ausdruck kann deren implizite Erfassung durch den enthaltenen Lambda-Ausdruck verursachen (siehe unten). Implizite odr-Verwendungen können zu impliziter Erfassung führen. -Ende note]

Ich dachte, dass der Beginn einer Phrase a lambda-expression with an associated capture-default jede implizite Erfassung verbieten sollte (und es wird von Kommentar bestätigt), deshalb #1 Aufruf zu einem Fehler führen wird (etwas nicht erfaßt Variable). So wie es funktioniert? Was wird das erste Argument von f sein? Was passiert, wenn g nach dem Verlassen des Bereichs test() aufgerufen wird? Was passiert, wenn ich die Signatur #1 in void(const int&) ändere?

-

upd: Vielen Dank an alle für die Erklärung, wie es funktioniert. Später werde ich versuchen, Referenzen zu diesem Fall zu finden und zu veröffentlichen.

+1

'x' ist ein konstanter Ausdruck. das ist ODR-nur für # 2 wegen der Referenz verwendet. – Jarod42

+1

Mit anderen Worten, 'g' verhält sich so, als wäre sein Körper' {f (17); } '. –

Antwort

0

Als T.C. sagte in seinem Kommentar, # 1 erfordert kein Capture als x ist zur Kompilierzeit bekannt und wird daher in das Lambda gebacken. Nicht unähnlich, wie die Funktion f zur Kompilierzeit bekannt ist, so dass sie nicht erfasst werden muss.

Ich glaube, wenn Sie f ‚s Signatur int const & ändern versuchen Sie nun die Adresse der Konstanten zu übergeben, die auf dem Stapel ist, damit Änderungen unterworfen, und es würde erfordern x nach Wert oder Referenz zu erfassen.