C++11: capturing variable breaks lambda expression?

Have a few situations I wanted to use a lambda expression to initialize a variable. Doing this will allow the lambda body to run once, when it doesn't need to be ran each time (when nothing changes.)

I liked the idea of doing this rather than setting a variable to a default value, then doing if statements and setting it, without needing to use an actual function.

If the lambda body is costly, could always try a static variable for the return value, and a static bool flagging whether the variable has been set, but I don't get why we'd have to go to that length to do this.

Does gcc 4.7.0 (build 20111106) have a bug in it that I'm running into, or does the lambda specifications indicate that you can't do a lambda expression when capturing variables?


This program compiles on gcc 4.7.0 (build 20111106):
1
2
3
4
5
6
7
8
9
int main() {
   bool thisWorks = [] {
      unsigned long number = 5;
      if(10 == number) {
         return false;
      }
      return true;
   };
}


This program generates a compilation error:
1
2
3
4
5
6
7
8
9
int main() {
   unsigned long number = 5;
   bool thisDoesntWork = [&] {   // note, these don't work either: [=], [&number], [number]
      if(10 == number) {
         return false;
      }
      return true;
   };   // note, this is the line the error falls on
}

<filename>.cpp:8:4: error: cannot convert `main()::<lambda()>` to `bool` in initialization


Thinking maybe the compiler needs help for some strange reason, I tried this. But, this program also generates a compilation error:
1
2
3
4
5
6
7
8
9
int main() {
   unsigned long number = 5;
   bool thisDoesntWork = [number]()->bool {
      if(10 == number) {
         return false;
      }
      return true;
   };   // note, this is the line the error falls on
}

<filename>.cpp:8:4: error: cannot convert `main()::<lambda()>` to `bool` in initialization
You're trying to to assign a lambda function to a bool variable. This works in the first example, because a lambda function that doesn't capture anything can be implicitly converted to a regular function pointer, which can be converted to true.

This is how it should be:
1
2
3
4
5
6
int main()
{
   unsigned long number = 5;
   auto func=[&](){return 10!=number;};
   //alternatively: auto func=[&]() -> bool {return 10!=number;};
}


You only have to specify the return type when the body consists of more than a single return statement.
Last edited on
Thanks!

Ahh, I see, the first example was compiling, but compiling differently than I expected. I never did test if the bool was being set correctly. I saw it compile, and assumed it worked as intended.

So, if I want to:
* initialize a variable
* and, the setting process is expensive - so I don't want to use a lambda function that runs several times
* and, the setting process can't be done in one line of code
* and I don't want to first initialize it to a default or invalid state than immediately try to re-assign it
* and I have to capture a variable(s)
* and I want the initialization code to be nearby, rather in a separate function
... is this my best option:

1
2
3
4
5
int main() {
   unsigned long number = 5;
   auto setNumber = [&] { return 10!=number; };
   bool thisWorks = setNumber();
}


I know this example looks silly, but it's a reduced case scenario. Setting this variable is 1 line of code, so lambda isn't needed, but I'm interested in when it's more than 1 line of code.
Need to assign lambda function pointer to auto... Then call the function.

Hope you second expression will work with following changes...

1
2
3
4
5
6
7
8
9
10
11
int main() {
   unsigned long number = 5;
   auto thisWorks = [number]()->bool {
      if(10 == number) {
         return false;
      }
      return true;
   };   
   bool (*func_ptr)() = thisWorks;
   bool bIsNot10 = func_ptr();
}
Well yes, if you have several objects that need to be initialized this way, then using a lambda function makes sense.

@richardforc
It's not necessary to convert a lambda function to a function pointer before calling it.
Nor is it even possible in this case, as only lambdas without captures can be converted to function pointers.
Last edited on
Athar - well, several objects being initialized this way, but many cases of each individual lambda function only initializing a single object rather than being re-used. Figure a lot of people would say it's silly. Just trying to meet my list of "I want to's" in my last post, which of course some people wouldn't care about.


To get more into why I'm wanting to be able to do something like this...

Never liked this style of setting variables, when they get more complex and many lines long:
1
2
bool someBool = false;  // default value
if(something) someBool = true;


And in some situations would like to avoid bool someBool = boolValueFunction(...).

Especially with enumerated types, I tend to use a _UNKNOWN enumerated type value, then have to periodically make sure it's not _UNKNOWN in switch statements, even though it should never come out that way, just to be sure.

Figuring doing this way, I won't have to use invalid default values like that, and can throw an exception if I can't set the variable properly.
Topic archived. No new replies allowed.