5

I'm studying c++11 especially interested in lambda.

After some practices, I assumed that lambda closure is an nameless function object.

So I wrote this code.

template <class callable_object>
void lambda_caller( callable_object lambda )
{
    std::cout<< sizeof(lambda) << endl;
    lambda();
}

I know that I can use std::function instead of using template, but I don't want the overhead while typecasting.

But I found one problem reading this question : Why can't I create a vector of lambda in C++11?

The answerer said, "Every lambda has a different type- even if they have the same signature.".

Compilers makes different codes for different classes.

So I think that my compiler will make another version of lambda_caller whenever I make another definition of lambda to pass.

Is there any way to avoid it, except using std::function? Isn't there any generic type for lambda closure?

Community
  • 1
  • 1
user2020192
  • 109
  • 1
  • 6
  • 2
    Wasn't `std::function` designed specifically for this? You could write your own wrapper for a lambda, that offers the same object type to client code and allows you to call whatever different lambda is bound to it, transparently. If you wrote a good implementation, you'd end up with std::function (or similar). – utnapistim Feb 21 '13 at 09:59
  • 3
    @utnapistim: `std::function` is for *storing* callables. If you just want to take any callable, use a template - it also enables easier inlining. And if you want to store it, still use a template, and internally convert to `std::function`. – Xeo Feb 21 '13 at 10:00
  • I didn't know about packaged_task. I use `std::function`s as input parameters, when I do not want (or need) to convert my class or functions to templates on the functor/lambda type (callbacks, event notification receivers, error handling policies, etc). – utnapistim Feb 21 '13 at 10:06
  • 1
    Unless an implementation decides to resort to deep magic, more often than not using `std::function` here will not save you anything (on top of being more troublesome and costly at runtime): a typical implementation will have a template constructor so different functor types will yield different instantiations of that constructor. In all likeliness there will also be *more* inner template machinery instantiations, too. The code you have right now is minimal -- there is very little you should change. – Luc Danton Feb 21 '13 at 17:23

2 Answers2

5

You can't avoid it. Lambda is just a class with operator()() overloaded which executes your code. So different code - different classes.

ixSci
  • 13,100
  • 5
  • 45
  • 79
0

std::function is the generic type for lambda closures. The problem is that each lambda may capture different variables. So it can't be reduced to say a function pointer and some data, because the lambda may have captured 3 variables or it may have captured 4. std::function will take care of making sure that enough memory is allocated for the data, but it comes at a cost(the data could be heap allocated).

However, if you are wanting to store several lambdas, and you know how many at compile-time. You could store them in an std::tuple instead. Which allows different types for each lambda. Unfortunately, C++ still doesn't provide a way to iterate over a tuple, but using Boost.Fusion you can.

Paul Fultz II
  • 17,682
  • 13
  • 62
  • 59
  • C++ provides a way -- I am only 109 characters short of being able to post a [complete example](http://liveworkspace.org/code/Hpv3w$25) in this comment. – Yakk - Adam Nevraumont Feb 25 '13 at 20:28
  • @Yakk Thats pretty cool. Of course, I didn't mean it was impossible, just that the standard C++ library doesn't provide a way. – Paul Fultz II Mar 03 '13 at 16:30
  • @PaulFultzII "`std::function` is the generic type for lambda closures." I think this statement is either not true, or at least misleading: https://stackoverflow.com/a/36030880. – CrepeGoat Dec 10 '22 at 01:37