Правило для лямбда-захвата переменной - PullRequest
7 голосов
/ 27 августа 2011

Например:

class Example
{
public:
    explicit Example(int n) : num(n) {}
    void addAndPrint(vector<int>& v) const
    {
        for_each(v.begin(), v.end(), [num](int n) { cout << num + n << " "; });
    }
private:
    int num;
};

int main()
{
    vector<int> v = { 0, 1, 2, 3, 4 };

    Example ex(1);
    ex.addAndPrint(v);
    return 0;
}

Когда вы компилируете и запускаете это в MSVC2010, вы получаете следующую ошибку:

ошибка C3480: 'Example :: num': переменная захвата лямбды должна быть из области действия функции

Однако, с g ++ 4.6.2 (prerelease) вы получите:

1 2 3 4 5

Какой компилятор прав в соответствии со стандартным проектом?

Ответы [ 2 ]

7 голосов
/ 27 августа 2011

5.1.2 / 9:

Область действия локального лямбда-выражения - это набор ограждающие области вплоть до самой внутренней ограждающей функции и его параметры.

и 5.1.2 / 10:

Идентификаторы в списке захвата ищутся с использованием обычных правил для поиска безоговорочного имени (3.4.1); каждый такой поиск должен найти переменная с автоматической продолжительностью хранения, объявленной в достижении область действия локального лямбда-выражения.

Так как num не объявлен ни в какой области функций, ни имеет автоматическую продолжительность хранения, он не может быть захвачен. Таким образом, VS прав, а g ++ неправильн.

0 голосов
/ 27 августа 2011

Стандарт говорит следующее (5.1.2):

Идентификаторы в списке захвата ищутся с использованием обычных правил для поиска безоговорочного имени (3.4.1); каждый такой поиск должен найти переменную с автоматической продолжительностью хранения, объявленной в области охвата локальной сети. лямбда-выражение.

Насколько я понимаю, компилятор GCC прав, потому что 'num' находится в области охвата в точке лямбда-объявления.

...