Что такое лямбда-захваты C ++ 0x

В одном из последних проектов 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

12
задан sellibitze 29 March 2011 в 13:26
поделиться