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 и новее распечатайте "Вы используете clang ++!" и предупредить о неиспользовании захвата
foo
.g ++ 4.9.0 и новее распечатайте «Вы используете g ++!» и предупредить о неиспользовании параметра
foo
.
Какой компилятор здесь более точно соответствует стандарту C ++?
struct Lambda { template<typename T> void operator()(T foo) const { /* ... */ } private: decltype(outer_foo) foo{outer_foo}; }
.Ответы:
Обновление: как и обещал председатель ядра в нижней цитате, код теперь неправильно сформирован :
Некоторое время назад было несколько проблем с поиском имени в лямбдах. Их разрешил N2927 :
Поиск всегда выполняется в контексте лямбда-выражения , а не «после» преобразования в тело функции-члена закрывающего типа. См. [Expr.prim.lambda] / 8 :
(Пример также проясняет, что поиск каким-то образом не учитывает сгенерированный член захвата типа закрытия.)
Имя
foo
не (повторно) объявлено в захвате; он объявлен в блоке, включающем лямбда-выражение. Параметрfoo
объявлен в блоке, который вложен в этот внешний блок (см. [Basic.scope.block] / 2 , в котором также явно упоминаются лямбда-параметры). Порядок поиска явно от внутренних блоков к внешним . Значит параметр должен быть выбран, то есть Clang прав.Если бы вы сделали захват init-capture, т.е.
foo = ""
вместо этогоfoo
, ответ был бы неясным. Это потому, что захват теперь фактически вызывает объявление, чей «блок» не задан. Я написал об этом основному стулу, и он ответилисточник
Я пытаюсь собрать несколько комментариев к вопросу, чтобы дать вам содержательный ответ.
Прежде всего, обратите внимание, что:
foo
Следовательно, логика заставит меня с первого взгляда сказать, что параметр должен затенять захваченную переменную, как если бы в:
В любом случае, @nm правильно заметил, что нестатические элементы данных, объявленные для переменных, захваченных копией, на самом деле не имеют имени. При этом доступ к безымянному элементу данных по-прежнему осуществляется с помощью идентификатора (то есть
foo
). Следовательно, имя параметра оператора вызова функции должно (позвольте мне сказать) затенять этот идентификатор .Как правильно указал @nm в комментариях к вопросу:
Из-за этого я бы сказал, что лязг - правильный.
источник