2 Replies - 294 Views - Last Post: 10 October 2019 - 07:27 AM Rate Topic: -----

#1 robgeek   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 190
  • Joined: 15-January 13

Lambda functions attribution problem when doing in c style.

Posted 09 October 2019 - 07:17 PM

In the following code why can't I define nothing inside the captures when I'm using c style attribution?
#include <iostream>

int main(int argc, const char *argv[])
{
	int x, y;

	x = 10;
	int (*sumA)() = [=] () { return (x + 5); };
	std::cout << sumA() << std::endl;

	x = 6;
	y = 13;
	//auto sumB = [=] () { return (x + y + 4); };
	//std::cout << sumB() << std::endl;

	return 0;
}


Error message:
main.cpp: In function ‘int main(int, const char**)’:
main.cpp:8:43: error: cannot convert ‘main(int, const char**)::<lambda()>’ to ‘int (*)()’ in initialization
  int (*sumA)() = [=] () { return (x + 5); };

I have no idea what this error message is trying to tell me because the problem seems to be in the capture nothing to do with conversion.

This post has been edited by robgeek: 09 October 2019 - 07:19 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Lambda functions attribution problem when doing in c style.

#2 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7085
  • View blog
  • Posts: 24,090
  • Joined: 05-May 12

Re: Lambda functions attribution problem when doing in c style.

Posted 09 October 2019 - 08:47 PM

To workaround the problem, you'll need to use:
auto sumA = [=] () { return (x + 5); };



As to why you need to do this, my understanding is that you can't use function pointers to lambda's if they have captures. Unfortunately, my understanding of why this is the case is very weak. My guess is that the compiler actually builds up an entire object around the actual lambda and the captured values, and the same way you can't have function pointers to non-static class members, the same would be true in this case. This is just a guess on my part, though. It would be great to hear from a C++ expert with more experience on how lambda's actually work, and not just point to a C++ ISO reference that says it is not allowed.

Also, I think that std::function<>, instead of auto should get you over the hump, but you still won't end up with an old fashioned C function pointer.
Was This Post Helpful? 2
  • +
  • -

#3 sepp2k   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2754
  • View blog
  • Posts: 4,414
  • Joined: 21-June 11

Re: Lambda functions attribution problem when doing in c style.

Posted 10 October 2019 - 07:27 AM

View Postrobgeek, on 10 October 2019 - 04:17 AM, said:

In the following code why can't I define nothing inside the captures when I'm using c style attribution?


Because lambdas can only be converted to function pointers if they have no captures. Your only choices are to not capture anything or to not use the lambda as a function pointer.

Quote

I have no idea what this error message is trying to tell me because the problem seems to be in the capture nothing to do with conversion.


That depends on your point of view. It's not like having a lambda with captures is by itself a problem. The compiler sees the lambda and has absolutely no problem with it or the fact that it captures everything. But then the compiler sees that you're trying to convert it to a function pointer and it says "Hey, you can't do that with a lambda that has captures".


View PostSkydiver, on 10 October 2019 - 05:47 AM, said:

Unfortunately, my understanding of why this is the case is very weak. My guess is that the compiler actually builds up an entire object around the actual lambda and the captured values, and the same way you can't have function pointers to non-static class members, the same would be true in this case.


Pretty much, or more accurately: a lambda will generally compile to the same machine code as a non-static non-virtual method of an object that contains the captured values and/or references. So in the machine code you'll have a function that takes as its first argument a pointer to memory that contains those values/references. Of course that's an implementation detail and the function could just as well take the captured values/references as individual arguments. Either way, the point is that you need to pass the captures along somehow. You can't have a zero-argument function that just magically has access to the variable x. And if you can't have a zero-argument function, you also can't have a zero-argument function pointer pointing to that function.

Technically, that's not quite true. You could implement by having the lambda compile to code that's dynamically generated whenever the lambda is instantiated. This dynamically generated code could then contain the addresses of the captured variables hard-coded because this way those addresses would be already known when the code is generated. Of course this would be rather expensive and there are platforms that don't support dynamically generated code at all. Also it isn't clear when the memory for the dynamically generated code should be freed. So it's good that C++ doesn't allow this, so none of these issues arise.
Was This Post Helpful? 2
  • +
  • -

Page 1 of 1