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 i nowsze wydrukuj "Używasz clang ++!" i ostrzegaj o niewykorzystaniu przechwytywania
foo
.g ++ 4.9.0 i nowsze wydrukuj "Używasz g ++!" i ostrzec o nieużywanym parametrze
foo
.
Który kompilator dokładniej postępuje zgodnie ze standardem C ++?
struct Lambda { template<typename T> void operator()(T foo) const { /* ... */ } private: decltype(outer_foo) foo{outer_foo}; }
.Odpowiedzi:
Aktualizacja: zgodnie z obietnicą krzesła Core w dolnym cytacie, kod to teraz źle sformułowany :
Jakiś czas temu było kilka problemów dotyczących wyszukiwania nazw w lambdach. Zostały rozwiązane przez N2927 :
Wyszukiwanie jest zawsze wykonywane w kontekście wyrażenia lambda , nigdy „po” transformacji do treści funkcji składowej typu zamknięcia. Zobacz [expr.prim.lambda] / 8 :
(Z przykładu jasno wynika również, że wyszukiwanie w jakiś sposób nie uwzględnia wygenerowanego elementu przechwytywania typu zamknięcia).
Imię
foo
nie jest (ponownie) deklarowane podczas brania; jest zadeklarowana w bloku zawierającym wyrażenie lambda. Parametrfoo
jest zadeklarowany w bloku, który jest zagnieżdżony w tym zewnętrznym bloku (zobacz [basic.scope.block] / 2 , który również wyraźnie wspomina o parametrach lambda). Kolejność wyszukiwania jest wyraźnie od bloków wewnętrznych do zewnętrznych . Stąd parametr powinien być wybrany, czyli Clang ma rację.Gdybyś miał zrobić przechwycenie jako przechwytywanie początkowe, tj.
foo = ""
Zamiastfoo
, odpowiedź nie byłaby jasna. Dzieje się tak, ponieważ przechwytywanie w rzeczywistości wywołuje teraz deklarację, której „blokada” nie została podana. Wysłałem wiadomość do głównego krzesła, który odpowiedziałźródło
Próbuję zebrać kilka komentarzy do pytania, aby udzielić Ci znaczącej odpowiedzi.
Przede wszystkim zwróć uwagę, że:
foo
Dlatego logika sprawiłaby, że na pierwszy rzut oka powiedziałbym, że parametr powinien przesłonić przechwyconą zmienną, jak gdyby:
W każdym razie @nm poprawnie zauważył, że niestatyczne elementy składowe danych zadeklarowane dla zmiennych przechwytywanych przez kopię są w rzeczywistości nienazwane. Mimo to dostęp do nienazwanego członka danych jest nadal możliwy za pomocą identyfikatora (to znaczy
foo
). Dlatego nazwa parametru operatora wywołania funkcji powinna nadal (pozwólcie mi powiedzieć) przesłonić ten identyfikator .Jak słusznie zauważył @nm w komentarzach do pytania:
Z tego powodu powiedziałbym, że brzęk jest właściwy.
źródło