Nicht-lokale Lambda- und Erfassungsvariablen - was bedeutet "Bereich sperren"

8

Ich spiele gerade mit c ++ 11 lambdas und habe ein Beispiel gefunden, das ich nicht verstehen kann. Nach dem Standard:

  

Ein Lambda-Ausdruck, dessen kleinster umschließender Bereich ein Blockbereich (3.3.3) ist, ist ein lokaler Lambda-Ausdruck; irgendein   andere Lambda-Ausdrücke dürfen in ihrem Lambda-Introducer keine Capture-Liste haben

Also habe ich ein triviales Beispiel erstellt:

%Vor%

Der Code in ideone: Ссылка

Ich habe erwartet, dass dieser Code nicht kompiliert wird, weil er die Variable im Nicht-Block-Bereich erfasst (oder zumindest denke, dass der Teil auto x = ... nicht im Block-Bereich liegt). Aber der Code kompiliert - ist es in Ordnung?

Wenn es in Ordnung ist - was ist der Blockumfang?

(Ich bin mir nicht sicher, welche Compiler-Version ich verwende, weil ich zur Zeit nur auf die IDEONE-Seite zugreifen kann.

Danke für die Erklärung!

    
matekm 13.10.2013, 12:01
quelle

1 Antwort

12

Es sieht so aus, als wäre dies eine Compiler-Erweiterung. g ++ 4.8.1 kompiliert dies unter Angabe einer Warnung:

  

Warnung: Erfassung der Variablen 'a' mit nicht-automatischer Speicherdauer [standardmäßig aktiviert]

clang ++ 3.4 kompiliert das nicht:

  

Fehler: 'a' kann nicht erfasst werden, da keine automatische Speicherdauer vorliegt

Beide beziehen sich auf [expr.prim.lambda] / 10

  

Die Identifikatoren in einer Capture-Liste werden nach den üblichen Regeln für die Suche nach unqualifizierten Namen (3.4.1) gesucht; Jede solche Suche sollte eine Variable mit automatischer Speicherdauer finden, die im reichweitenreichen Bereich des lokalen Lambda-Ausdrucks deklariert ist.

Es sieht so aus, als würden sie nicht zusätzlich den umschließenden Gültigkeitsbereich des Lambda überprüfen, ich kann mir vorstellen, dass es überflüssig wäre (es gibt keine Namen von Variablen mit automatischer Speicherdauer im Nicht-Block- / Namespace-Bereich).

Ein Blockbereich ist in [basic.scope.block] / 1

definiert
  

Ein in einem Block (6.3) deklarierter Name ist lokal für diesen Block; Es hat einen Blockbereich.

Und ein Block ist definiert als:

  

Damit mehrere Anweisungen verwendet werden können, wenn eine erwartet wird, wird die zusammengesetzte Anweisung (ebenfalls und "Block" genannt) bereitgestellt.

     

zusammengesetzte Aussage:
   { Anweisung-seq opt }

Sie haben also Recht, dass Ihr global deklariertes Lambda nicht in einem Blockbereich ist.

    
dyp 13.10.2013, 12:15
quelle

Tags und Links