Jump to content
  • Advertisement
MarcusAseth

What is the type of a Lambda with capture?

This topic is 496 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Premise: this question is just out of curiosity, I don't need to use this knowledge, therefore answers like "you don't need to do it" or "just use auto" are invalid. This is for science :D

The code below compile:

#include <iostream>
using namespace std;

int(*myFunction(int b))(int a)
{
	int(*f)(int a) = [](int a) { int myVariable = a ; return ++myVariable; };
	return f;
}

int main()
{
	while (true){
		cout << myFunction(5)(12);
	}
}

Now if I change the lambda to capture b, the code doesn't compile anymore, code below:

int(*myFunction(int b))(int a)
{
	int(*f)(int a) = [b](int a) { int myVariable = a + b; return ++myVariable; };
	return f;
}

so my question is, what does the lambda type being assigned to "f" when I add the capture changes into?

How would you re-write "int(*f)(int a)" such that it compiles when there is that capture of "b"? (no auto, typedef, using or other tricks allowed, I want to see the ugly form :D)

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
Advertisement

The type is anonymous. Only the compiler knows it, there's no way to determine what it is. A lambda with a capture tends to compile down to something like:

// this
auto f = [a](int x) -> int
{
   return x + a + 2;
};

// turns into this
struct
{
  int a;
  
  int operator()(int x) 
  {
    return x + a + 2;
  }
} f {a};

You can't use a function pointer type to refer to a lambda with a capture. std::function will allow you to do what you're trying to do:

std::function<int(int b)> myFunction(int a)
{
	std::function<int(int b)> = [](int a) { int myVariable = a ; return ++myVariable; };
	return f;
}

Otherwise... Just use auto.

Edited by Oberon_Command

Share this post


Link to post
Share on other sites

I think you're starting to bump against the reason the standards committee had to accept the updated version of auto.  People had been pushing for it for years, but to get all the lambda functionality in required some unnamable types. The simpler versions generate an anonymous class with a functor, meaning operator(), which gives the result. 

 

Lambdas without a capture can be converted to a function pointer. That is guaranteed in the standard, and easy enough to figure out how to mimic with function objects like @Oberon_Command did above.  The compiler generates them as anonymous objects, but you could do it yourself.

Lambdas with a capture can sometimes be converted, but sometimes not. When you start dealing with captures there are edge cases that I never really understood that made it impossible to think of as a regular function object.  These cannot be generated with an actual type in C++, they are unnameable, so they were called Lambda Closures and can only be referred to with auto.  Their actual type is basically "block of code".

 

Since nobody can actually name what the type is, you've got to use auto.

Share this post


Link to post
Share on other sites
4 minutes ago, frob said:

Since nobody can actually name what the type is, you've got to use auto.

Which is also less headache, so I don't complain :P

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!