лямбда-выражение (MSVC ++ против g ++) - PullRequest
6 голосов
/ 09 июля 2010

У меня есть следующий код

#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>


int main()
{
  typedef std::vector<int> Vector; 
  int sum=0;
  Vector v;
  for(int i=1;i<=10;++i)
     v.push_back(i);

  std::tr1::function<double()>  l=[&]()->double{

    std::for_each(v.begin(),v.end(),[&](int n){sum += n; //Error Here in MSVC++});
    return sum;
     };

  std::cout<<l();
  std::cin.get();
}

Приведенный выше код выдает ошибку на MSVC++ 10, тогда как он прекрасно компилируется с g++ 4.5. Произошла ошибка 1 IntelliSense: invalid reference to an outer-scope local variable in a lambda body c:\users\super user\documents\visual studio 2010\projects\lambda\lambda.cpp 19 46 lambda

Итак, есть ли другой способ доступа к переменной внешней области sum без явного создания новой переменной внутри локального лямбда-выражения (внутри std::for_each)?

На g++ 4.5 код компилируется нормально. Говорит ли что-нибудь об этом в стандарте (черновик n3000) (в настоящее время у меня нет копии стандарта C ++ - 0x (1x?))

Ответы [ 4 ]

15 голосов
/ 11 июля 2010

Вы на самом деле пытались скомпилировать код в вопросе?Visual C ++ 2010 принимает код как есть (очевидно, с удаленным комментарием) и успешно компилирует код без ошибок.

«Ошибка», которую вы видите, является не ошибкой компиляции, а ошибкой IntelliSense.Проверка ошибок IntelliSense приводит к множеству ложных срабатываний (за последние несколько месяцев я сообщал о нескольких ошибках в Microsoft Connect);в этом случае IntelliSense неправильно говорит, что это ошибка, когда это не так.

У вас есть два варианта: вы можете игнорировать ложные срабатывания IntelliSense или отключить проверку ошибок IntelliSense (щелкните правой кнопкой мыши Список ошибокСнимите флажок «Показать ошибки IntelliSense»).

В любом случае, эти ошибки IntelliSense никоим образом не препятствуют успешной компиляции.

1 голос
/ 11 июля 2010

Независимо от того, является ли VC неправильным или правильным, это плохой стиль, когда вы объявляете сумму вне вашей (внешней) лямбды.Так как вы возвращаете значение sum, нет необходимости изменять значение внешней переменной внутри цикла.Вместо этого у вас должно быть:

int sum = 0;
std::for_each(v.begin(),v.end(),[&](int n){sum += n;});
return sum;

Возможно, вложенные лямбды также сбивают с толку виртуальный канал.Я бы сказал, что иметь вложенные лямбды - это излишне, и это делает код менее читаемым.

0 голосов
/ 23 июля 2010

Я думаю, что единственная проблема, с которой вы столкнулись - это красная волна муравья размера .... С тех пор Microsoft выпустила компилятор ранее, и вскоре орган по стандартизации изменил правило поиска имен ... так что intellisense не обновлен ........

ТАК, ЧТОБЫ ПОПРОБОВАТЬ ЭТУ ИДЕЮ ..... РЕБЕНОК ...

#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>


int main()
{
  typedef std::vector<int> Vector; 
  int sum=0;
  Vector v;
  for(int i=1;i<=10;++i)
     v.push_back(i);

  std::tr1::function<double()>  l=[&]()->double{
      int *y; y=&sum;
      std::for_each(v.begin(),v.end(),[&](int n){*y += n; });
    return sum;
     };

  std::cout<<l();
  std::cin.get();
}
0 голосов
/ 09 июля 2010

Я думаю, что вам, возможно, придется явно объявить закрытие над sum, например, так:

std::for_each(v.begin(),v.end(),[&sum](int n){sum += n;});

В общем, вам разрешено неявно захватывать переменные в локальной области видимости, нотолько до тех пор, пока лямбда гарантированно будет работать в том же объеме.Возможно, из-за того, что вы назначаете лямбду функции var и выполняете ее позже (вместо того, чтобы просто запускать ее напрямую), MSVC не достаточно умен, чтобы понять, что это условие выполняется - в конце концов, вы могли бы потенциально передать l и выполнитьэто в некоторой другой области - так что это требует явного объявления захвата.

...