Lambda-Ausdruck in C ++, OS X's clang vs GCC

8

Eine besondere Eigenschaft der Lambda-Ausdrücke von c ++ ist die Erfassung der Variablen in dem Bereich, in dem sie deklariert sind. Zum Beispiel kann ich eine deklarierte und initialisierte Variable c in einer Lambda-Funktion verwenden, auch wenn 'c' nicht als Argument gesendet wird, sondern von '[]':

%Vor%

Die erwartete Ausgabe ist also 10. Das Problem tritt auf, wenn mindestens zwei Variablen, die eine erfasst und die andere als Argument gesendet wird, den gleichen Namen haben:

%Vor%

Ich denke, dass der 2011-Standard für C ++ besagt, dass die eingefangene Variable Vorrang vor den Argumenten des Lambda-Ausdrucks hat, wenn die Namen übereinstimmen. Bei der Kompilierung des Codes mit GCC 4.8.1 unter Linux ist die Ausgabe, die ich erhalte, die erwartete, 5 . Wenn ich denselben Code mit der apple-Version des clang-Compilers (clang-503.0.40, der mit Xcode 5.1.1 auf Mac OS X 10.9.4 gelieferten) kompiliere, bekomme ich die andere Antwort, 3 .

Ich versuche herauszufinden, warum das passiert; ist es nur ein Apple-Compiler-Bug (wenn der Standard für die Sprache wirklich besagt, dass das eingefangene "c" Vorrang hat) oder etwas Ähnliches? Kann dieses Problem behoben werden?

BEARBEITEN

Mein Lehrer hat eine E-Mail an den GCC-Helpdesk geschickt und sie haben geantwortet, dass es sich eindeutig um einen Fehler des GCC-Compilers handelt, und melden Sie ihn Bugzilla. Also ist Clangs Verhalten das Richtige!

    
pier94 19.07.2014, 10:07
quelle

2 Antworten

1

Aus dem C ++ 11 Standard, 5.1.2 "Lambda-Ausdrücke" [expr.prim.lambda] # 7:

Die lambda-expression compound-Anweisung liefert den function-body (8.4) des Funktionsaufrufoperators. aber zum Zwecke der Namenssuche (3.4), Bestimmen des Typs und Wertes von this (9.3.2) und Transformieren von id-expressions s Verweisen auf nicht statische Klassenmitglieder in Zugriffsberechtigungen für Klassenmitglieder mit (*this) (9.3.1), die compound-Anweisung wird im Zusammenhang mit dem Lambda-Ausdruck betrachtet

Auch von 3.3.3 "Block scope" [basic.scope.local] # 2:

Der potenzielle Geltungsbereich eines Funktionsparameternamens (einschließlich einer Angabe in einem lambda-declarator ) oder von Eine funktions-lokale vordefinierte Variable in einer Funktionsdefinition (8.4) beginnt an ihrem Deklarationspunkt.

Namen in einer Aufnahmeliste sind keine Deklarationen und haben daher keinen Einfluss auf die Namenssuche. In der Erfassungsliste können Sie nur die lokalen Variablen verwenden. es führt ihre Namen nicht in den Geltungsbereich des Lambda ein. Beispiel:

%Vor%

Da die Parameter zu einem Lambda in einem inneren Blockbereich liegen und da die Namenssuche im Kontext des Lambda-Ausdrucks erfolgt (nicht etwa der generierten Klasse), verbergen die Parameternamen tatsächlich die Variablennamen die umschließende Funktion.

    
Eric M Schmidt 19.07.2014, 15:31
quelle
2

Nach meinem Verständnis der folgenden Punkte des c ++ 11 Standards:

  

5.1.2 Lambda-Ausdrücke

     

3 Der Typ des Lambda-Ausdrucks (der auch der Typ des Closure-Objekts ist) ist ein eindeutiger, unbenannter Nicht-Vereinigungsklassen-Typ - genannt   der Verschlusstyp - dessen Eigenschaften im Folgenden beschrieben werden.

     

...

     

5 Der Closure-Typ für einen Lambda-Ausdruck hat einen öffentlichen Inline-Funktionsaufrufoperator (13.5.4), dessen Parameter und Rückgabetyp sind   beschrieben durch die parameter-deklaration-Klausel des Lambda-Ausdrucks und   Trailing-Return-Typ jeweils. Dieser Funktionsaufruf-Operator ist   deklariert const (9.3.1) genau dann, wenn der Lambda-Ausdruck   Auf die Parameter-Deklarationsklausel folgt keine Änderbarkeit.

     

...

     

14 Für jedes durch copy erfasste Objekt wird ein nicht benanntes nicht statisches Datenelement im Verschlusstyp

deklariert

Ein Lambda-Ausdruck wie dieser ...

%Vor%

... entspricht ungefähr einer Klasse / Struktur wie folgt:

%Vor%

Ich würde also erwarten, dass der Parameter das erfasste Mitglied ausblenden würde.

BEARBEITEN:

In Punkt 14 aus dem Standard (oben zitiert) scheint das aus der erfassten Variablen erstellte Datenelement * zu sein. unbenannt * . Der Mechanismus, nach dem es referenziert wird, scheint unabhängig von den normalen Bezeichner-Lookups zu sein:

  

17 Jeder ID-Ausdruck, der eine odr-use (3.2) einer durch copy erfassten Entität ist, wird in einen Zugriff auf das entsprechende unbenannte Datenelement der Schließungstyp.

Es ist unklar, ob ich beim Lesen des Standards entscheiden sollte, ob diese Transformation Vorrang vor der Parametersymbolsuche haben soll.

Vielleicht sollte dies also als UB (undefiniertes Verhalten) markiert werden?

    
Galik 19.07.2014 11:07
quelle

Tags und Links