auto foo = "You're using g++!";
auto compiler_detector = [foo](auto foo) { std::puts(foo); };
compiler_detector("You're using clang++!");
clang ++ 3.6.0 und neuerer Ausdruck "Sie verwenden clang ++!" und warnen Sie davor, dass die Aufnahme
foo
nicht verwendet wird.g ++ 4.9.0 und neuerer Ausdruck "Sie verwenden g ++!" und warnen, dass der Parameter
foo
nicht verwendet wird.
Welcher Compiler folgt hier genauer dem C ++ - Standard?
struct Lambda { template<typename T> void operator()(T foo) const { /* ... */ } private: decltype(outer_foo) foo{outer_foo}; }
.Antworten:
Update: Wie vom Core Chair im unteren Zitat versprochen, ist der Code jetzt schlecht geformt :
Vor einiger Zeit gab es einige Probleme bei der Namenssuche in Lambdas. Sie wurden von N2927 gelöst :
Die Suche erfolgt immer im Kontext des Lambda-Ausdrucks , niemals "nach" der Transformation in den Elementfunktionskörper eines Schließungstyps. Siehe [expr.prim.lambda] / 8 :
(Das Beispiel macht auch deutlich, dass bei der Suche das generierte Erfassungselement des Schließungstyps nicht berücksichtigt wird.)
Der Name
foo
wird in der Aufnahme nicht (neu) deklariert. Es wird in dem Block deklariert, der den Lambda-Ausdruck enthält. Der Parameterfoo
wird in einem Block deklariert, der in diesem äußeren Block verschachtelt ist (siehe [basic.scope.block] / 2 , in dem auch Lambda-Parameter explizit erwähnt werden). Die Reihenfolge der Suche ist eindeutig von inneren zu äußeren Blöcken . Daher sollte der Parameter ausgewählt werden, dh Clang ist richtig.Wenn Sie die Erfassung zu einer Init-Erfassung machen würden, dh
foo = ""
stattdessenfoo
, wäre die Antwort nicht klar. Dies liegt daran, dass die Erfassung jetzt tatsächlich eine Deklaration induziert, deren "Block" nicht angegeben ist. Ich habe den Hauptstuhl darüber informiert, der geantwortet hatquelle
Ich versuche, ein paar Kommentare zu der Frage zusammenzufassen, um Ihnen eine aussagekräftige Antwort zu geben.
Beachten Sie zunächst Folgendes:
foo
Daher würde die Logik mich auf den ersten Blick sagen lassen, dass der Parameter die erfasste Variable wie folgt beschatten sollte:
Wie auch immer, @nm hat richtig bemerkt, dass die nicht statischen Datenelemente, die für kopiererfasste Variablen deklariert wurden, tatsächlich unbenannt sind. Davon abgesehen wird auf das unbenannte Datenelement weiterhin über eine Kennung (dh
foo
) zugegriffen . Daher sollte der Parametername des Funktionsaufrufoperators diesen Bezeichner immer noch (sagen wir mal) schattieren .Wie von @nm in den Kommentaren zur Frage richtig hervorgehoben:
Aus diesem Grund würde ich sagen, dass das Klirren richtig ist.
quelle