Passing Lambdas

So I saw at some point someone said something(wow, super specific, I know) about how lambdas in c++ we’re just syntactic sugar for a previous thing of making a class or something that has the function as it’s call operator or something like that. That kinda clears up what the auto is in the end, so could I, instead of passing a lambda to a function, pass the type of the lambda? Because from what I think is going on, it’s a class so the function isn’t initialized, only maybe the capture? Like could I have

1
2
3
4
5
6
7
  auto lambda = [] (int x,int y) { return x+y/2;  };
  
  template <class funcT>
  int performOp(args...){ // sorry if the ... op is wrong, I never use it.
    funcT a;
    return a(args...);
  }
Last edited on
The name of the type of your lambda function is not specified, you can't get a name for it directly.

funcT a;
A lambda can't be constructed like that.
(1) lambda is an object, not a type.
(2) even if you did decltype(lambda), I don't think it has a default constructor (or something like that).
gplusplus wrote:
note: a lambda closure type has a deleted default constructor


I'm no expert, so I'll just quote Cubbi.

http://www.cplusplus.com/forum/general/112742/
Cubbi wrote:
<quote>I thought the lambda expression I wrote would decay to a function pointer</quote>

template argument deduction doesn't attempt implicit conversions, but even if you forced it by instantiating callback<+lambda>(), it wouldn't work because non-type template argument that is a function pointer must point to a function with external linkage: in order to be a part of the type, it must be a compile-time constant. What you get when decaying a lambda into a pointer isn't one. Also, the conversion operator isn't constexpr.

Why not parametrize your callback on the type of the functor, rather than its address?


I would suggest just passing the lambda function as the first parameter.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Example program
#include <iostream>
 
// pass function as parameter
// https://stackoverflow.com/a/6614387/8690169
template<typename Func, typename... Args>
auto performOp(Func func, Args&&... args)
-> typename std::result_of<Func(Args...)>::type
{
    return func(std::forward<Args>(args)...);
}
 
int main()
{
    auto lambda = [] (int x,int y) { return x+y/2;  };
    
    decltype(lambda) lambda2(lambda);
    
    using std::cout;
    cout << lambda(3, 2) << '\n';
    cout << lambda2(3, 2) << '\n';
    cout << performOp(lambda, 3, 2) << '\n';
}
Last edited on
Ok, so the SO link you included helped me understand that it is for calling a ...uh... function pointer. But I don’t get how it works, and the person who wrote it never explains it. Would you mind explaining that part of it to me?

Edit: (I mean lines 6 to 11), Sry should have been more specific lol.
Last edited on
It's not a function pointer in that example, although the thing Cubbi mentioned about doing "+lambda" does make it a function pointer.
It's the lambda object itself being passed.
And when I said "lambda function", I guess it's more proper to call it a "lambda closure".

I can't really give a real technical explanation, but for the SO post, the function template takes in an object that uses the () operator, and "forwards" the arguments (Args...) so that the func can call the values arguments. The forwarding makes there be no extra run-time copying of arguments, I believe.

I'm not giving an opinion on its usefulness of that particular example, or whether or not it just adds to obfuscation, but it does show valid use of the "..." syntax.
Last edited on
Ok. Thanks!
Registered users can post here. Sign in or register to post.