В одном из последних проектов C ++ 0x (n3225.pdf) мы можем найти 5.1.2 / 10:
Идентификаторы в списке захвата ищутся с использованием обычного правила поиска неквалифицированного имени (3.4.1); каждый такой поиск должен найти переменную с автоматической продолжительностью хранения, объявленной в области действия локального лямбда-выражения. Сущность (т.е. переменная или это) считается явно захваченной, если она появляется в списке захвата лямбда-выражения.
Это кажется довольно ограничивающим для меня. Например, мне кажется , что следующие вещи запрещены:
int global;
struct s {
int x;
void memfun() {
[x,global]{};
}
};
, поскольку x
не обязательно является переменной с автоматическим хранением и не является глобальной
. Обратите внимание, что цель этого предложения захвата - позволить лямбда-объекту хранить копию из x
и global
, что может быть желательно в случае их изменения в поздняя стадия. Мне уже известна альтернатива:
int global;
struct s {
int x;
void memfun() {
int copyx = x;
int copyglobal = global;
[copyx,copyglobal]{};
}
};
Но это сводится к дополнительным копиям и дополнительному шаблону для захвата x
и global
в качестве копии.
Кроме того, я не могу найти что-нибудь убедительное в последних черновиках относительно того, что произойдет, если мы назовем локальную ссылку в предложении захвата:
int main() {
int i = 0;
int &r = i;
assert([r]{return &r;}() != &i);
}
Лямбда-объект «копирует ссылку» или «копирует int»? Если он захватывает упомянутый объект копией, это может сэкономить нам дополнительные копии от предыдущего обходного пути.
GCC очевидно поддерживает все эти примеры и сохраняет копию int в последнем случае (что желательно, IMHO). Но я хотел бы знать, является ли это на самом деле предполагаемым поведением в соответствии с черновиками C ++ 0x или просто расширением компилятора, соответственно, ошибкой реализации.
Изменить:
templatetypedef указал 5.1.2 / 14, который объясняет, что происходит, когда ссылка упоминается в предложении захвата. Насколько я могу судить, это позволяет нам использовать следующий обходной путь для первого примера:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
Tia, Но я хотел бы знать, является ли это на самом деле предполагаемым поведением в соответствии с черновиками C ++ 0x или просто расширением компилятора, соответственно, ошибкой реализации.
Изменить:
templatetypedef указал 5.1.2 / 14, который объясняет, что происходит, когда ссылка упоминается в предложении захвата. Насколько я могу судить, это позволяет нам использовать следующий обходной путь для первого примера:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
Tia, Но я хотел бы знать, является ли это на самом деле предполагаемым поведением в соответствии с черновиками C ++ 0x или просто расширением компилятора, соответственно, ошибкой реализации.
Изменить:
templatetypedef указал 5.1.2 / 14, который объясняет, что происходит, когда ссылка упоминается в предложении захвата. Насколько я могу судить, это позволяет нам использовать следующий обходной путь для первого примера:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
Tia, sellibitze