lambda expression (MSVC++ vs g++)
Asked Answered
E

4

6

I have the following code

#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();
}

The above code produces an error on MSVC++ 10 whereas it compiles fine with g++ 4.5. The error produced is 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

So, is there any other way to access the outer-scope variable sum without explicitly creating a new variable inside the local lambda expression(inside std::for_each)?

On g++ 4.5 the code compiles fine. Does the standard(n3000 draft) say anything about it?(I don't have a copy of C++-0x(1x ?) standard at present)

Emad answered 9/7, 2010 at 8:44 Comment(3)
VS10 doees have some known bugs related to lambda capture scope, som most likely GCC is right in this case.Doorpost
just download a recent standard draft - looking for "c++ standard" on Google you give you a link for it. It's an interesting learning experience to take a look on it :)Ddt
Note that the latest draft is the FCD, N3092, which you can download from the WG21 website (warning: 10.5MB PDF).Bratcher
B
12

Have you actually tried compiling the code in the question? Visual C++ 2010 accepts the code, as is (with the comment removed, obviously), and successfully compiles the code without error.

The "error" you are seeing is not a compilation error, but an IntelliSense error. The IntelliSense error checking results in a lot of false positives (I've reported several bugs on Microsoft Connect over the past few months); in this case, IntelliSense is incorrectly saying this is an error when it is not.

You have two options: you can ignore the IntelliSense false positives or you can disable the IntelliSense error checking (right-click the Error List window and uncheck "Show IntelliSense Errors").

Either way, these IntelliSense errors in no way prevent compilation from succeeding.

Bratcher answered 11/7, 2010 at 5:18 Comment(0)
D
1

Regardless of whether VC is wrong or right, it's bad style that you have sum declared outside your (outer) lambda. Since you return the value of sum, there's no need to be changing the value of an outer variable inside the loop. Instead, you should have:

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

It could be that the nested lambdas are confusing VC, too. I'd say it's overkill to have nested lambdas, and makes for less readable code.

Deficiency answered 11/7, 2010 at 2:9 Comment(0)
L
0

I think you may have to explicitly declare the closure over sum, like so:

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

In general, you're supposed to be allowed to implicitly capture variables in the local scope, but only as long as the lambda is guaranteed to run in the same scope. Possibly because you're assigning your lambda to a function var and executing it later (instead of just running it directly), MSVC isn't smart enough to understand that that condition holds - after all, you could potentially pass l and execute it in some other scope - so it requires the explicit capture declaration.

Liquescent answered 9/7, 2010 at 8:53 Comment(0)
B
0

I think the sole problem you have is with that ant size red wave.... SINCE microsoft had released the compiler earlier and soon the standards body did change the rule for name look up ...so intellisense isnt upto date........

SO TRY HITTING WITH THIS IDEA.....BABY...

#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();
}
Bernina answered 22/7, 2010 at 22:17 Comment(3)
I have already got the answer and solved my problem. BTW there is no need to use a raw_pointer here. Even a reference to sum would have solved the problem. BTW you can turn off that show intellisense errors option. I hope you know that. However the code is technically correct so I've mentioned it here also: https://mcmap.net/q/92460/-how-to-sum-up-elements-of-a-c-vector/…Emad
if your code was technically correct I dont find a reason for posting such silly errors here in a forum .... i think if you are a good programmer you wont shot a bread in public ,so all the dogs will run after that,( an analogy to the members in this forum)... they try discussing things instead of helping out........Bernina
This is not a discussion forum but a Q and A site. Initially I wasn't sure about the validity of the code in MSVC++ but after reading James' answer I realized that the error was merely an intellisense error and my code was perfectly valid. I am free to do whatever I want. If you don't like my question(or answer) don't post your answers/comments then. Its not at all required. they try discussing things instead of helping out Questions which are subjective and augmentative are closed immediately. It seems you are new to this site.Emad

© 2022 - 2024 — McMap. All rights reserved.