2014-01-27 2 views
10

AFAIK, C++ 11/14 не позволяет определять новый тип возвращаемого типа на месте при определении лямбда. Однако, похоже, выражение Camba capture lambda C++ 14 по существу создает анонимный тип с одним или несколькими «членами» и оператором(). Итак, почему компилятор не разрешает доступ к захваченным членам от за пределами лямбда. Мой слабый ум не может справиться с сложностями C++, но звучит ли он как разумное расширение языка? Вот пример.Доступ к C++ 14 лямбда-захватам, таким как элементы структуры

vector<string> words = { "Stack", "Overflow" }; 
auto l = [w = words](){}; // almost like a C# anonymous type 
cout << l.w[0]; // does not work. 
+0

* «AFAIK, C++ 11/14 не позволяет определять на месте определение нового типа при определении лямбда». * Что вы имеете в виду? Внутри лямбда-захвата или внутри лямбда-тела? – dyp

+0

Я хочу сказать больше, как новый тип возврата. – Sumant

+0

AFAIK, есть анонимные локальные классы в C++ 'vector words = {" Stack "," Overflow "}; struct {decltype (words) w; } l {words}; cout << lw [0]; '[Live example] (http://coliru.stacked-crooked.com/a/95fc5770a6a0036d) – dyp

ответ

5

Если я понимаю это право, вы хотите иметь доступ к переменной, которая запечатлена в лямбда. Но согласно верхнему ответу на Get captured variables from lambda?, это невозможно.

Это невозможно дизайн

5.1.2 [expr.prim.lambda]

15 [...] Для каждого объекта, захваченного копии, неназванный, не -статический элемент данных объявляется в типе замыкания. Порядок объявления этих членов не указан. [...]

16 [...] Неизвестно, являются ли дополнительные неназванные нестатические элементы данных , объявленные в типе замыкания для объектов, захваченных ссылкой.

Захваченные переменные безымянный (или, по крайней мере, имеют имена, невыразимое смертными) и порядок их декларации заведомо неопределенные. Базовые ссылки могут даже не существовать в закрытии типа.

Смелый акцент мой.

+0

Вздох! Хотелось бы, чтобы это был доступный именованный нестатический член в случае захвата копией. – Sumant

+4

Как я уже сказал в цитируемом ответе, вы действительно этого не хотите, вы только думаете, что это так. Поддержка того, что вы хотите, будет ограничивать реализацию и предотвращать оптимизацию. Если вы хотите получить доступ к именованным членам, тогда ** не используйте лямбда-выражение! ** –

17

статус-кво

Это обсуждалось, когда лямбда Инициализационные-захваты были добавлены к языку. В настоящее время рабочий проект стандарта (N3797) говорит (в [expr.prim.lambda] p11):

Для каждого INIT-захвата нестатический элемент данных назван идентификаторомinit-capture объявлен в типе замыкания.

Стандарт делает не указать доступ этого пользователя, что делает его неясно, будет ли это справедливо:

auto x = [n(0)] {}; 
int k = x.n; // ok? 

Это и некоторые другие проблемы спецификации с Init-захватами привели к национальному органу комментарий GB3 о стандартном проекте, который обрабатывается рабочей группой ядра C++ как core issue 1760.При обсуждении этого вопроса основная рабочая группа решила, что инициативных записей должно быть , а не быть доступными членами объекта замыкания.

Разрешение на выпуск 1760 (который утвержден РГС, но еще не в полной комиссии) изменяет спецификацию вместо сказать:

INIT захвата ведет себя так, как будто он объявляет и явно захватывает переменная формы “auto init-capture ;” которой декларативный область является лямбда-выражение «s соединение-оператор [...]

Этот новый ш ording дает понять, что начальный захват не добавляет именного элемента закрывающего объекта, а вместо него действует как любой другой захват лямбды.

Как расширения языка

Making Init-захватам быть доступными членами типа закрытия, конечно, можно (и моя первоначальная реализация Init-захватов в звоне сделал это, прежде чем я реализован решение вопроса 1760). Это также похоже на полезную функцию, но это также позволило бы нарушить инкапсуляцию лямбда-выражений в обычном случае, когда начальные записи не должны быть видимыми.

Смежные вопросы