Show lambda with parameters are used? How to pass parameters to them?
It works exactly like with any other type of callable object:
#include <iostream>
int main()
{
auto l = [] (int i) { std::cout << "The answer is " << i; };
l(42);
}
Also notice, that you do not need to store a lambda in a variable in order to invoke it. The following is an alternative way to rewrite the above program:
#include <iostream>
int main()
{
[] (int i) { std::cout << "The answer is " << i; } (42);
// ^^^^
// Invoked immediately!
}
The type of a lambda function (the so-called "lambda closure") is defined by the compiler, and is a functor with a call operator whose signature is the one you specify when defining the lambda. Therefore, you call a lambda exactly as you would call a functor (i.e. exactly as you would call a function - or any callable object).
Thus, if you want to assign a lambda to an object, the best practice is to let the compiler deduce its type by using auto. If you do not want or cannot use auto, then you may:
Use function pointers for non-capturing lambdas (capturing lambdas are not convertible to function pointers). In the above case, thus, the following will also work:
#include <iostream> int main() { void (*f)(int) = [] (int i) { std::cout << "The answer is " << i; }; f(42); }Use
std::function(this is always possible, even if the lambda is capturing):#include <iostream> #include <functional> int main() { std::function<void(int)> f = [] (int i) { std::cout << "The answer is " << i; }; f(42); }
c++ - C++11 lambda function - how to pass parameter - Stack Overflow
How do I pass a lambda to a method as a parameter?
When to use a lambda over a function pointer?
Use a lambda as a parameter for a C++ function - Stack Overflow
Videos
Show lambda with parameters are used? How to pass parameters to them?
It works exactly like with any other type of callable object:
#include <iostream>
int main()
{
auto l = [] (int i) { std::cout << "The answer is " << i; };
l(42);
}
Also notice, that you do not need to store a lambda in a variable in order to invoke it. The following is an alternative way to rewrite the above program:
#include <iostream>
int main()
{
[] (int i) { std::cout << "The answer is " << i; } (42);
// ^^^^
// Invoked immediately!
}
The type of a lambda function (the so-called "lambda closure") is defined by the compiler, and is a functor with a call operator whose signature is the one you specify when defining the lambda. Therefore, you call a lambda exactly as you would call a functor (i.e. exactly as you would call a function - or any callable object).
Thus, if you want to assign a lambda to an object, the best practice is to let the compiler deduce its type by using auto. If you do not want or cannot use auto, then you may:
Use function pointers for non-capturing lambdas (capturing lambdas are not convertible to function pointers). In the above case, thus, the following will also work:
#include <iostream> int main() { void (*f)(int) = [] (int i) { std::cout << "The answer is " << i; }; f(42); }Use
std::function(this is always possible, even if the lambda is capturing):#include <iostream> #include <functional> int main() { std::function<void(int)> f = [] (int i) { std::cout << "The answer is " << i; }; f(42); }
auto lambda = [] (int a, int b) { return a + b; };
assert(lambda(1, 2) == 3);
I've looked over the top dozen or so google posts related to this and similarly worded queries, but I'm still not fully understanding what I'm doing or if it's even possible the way I want to do it.
This is basically what I'm trying to do:
//some function that takes in a lambda and executes it
public static void testFunc(Func<int, int> x){
Console.WriteLine(x(3, 4));
}
//the call to the function, where a lambda is passed in for x
testFunc((x, y) => (x + y));Obviously this is way wrong! And I'm the first to admit I don't fully (or even close to) understand lambdas. But this is a result of my desire to be able to avoid explicit delegates for a bunch of functions that are simple arithmetic operations (for the sake of evaluating a postfix string)
Thanks for any help!
Question seems simple enough.
I've never really understood then point of lambdas. To me the code seems messy, why not use a function pointer instead?
You have 2 ways: make your function template:
template <typename F>
void myFunction(F&& lambda)
{
//some things
}
or erase type (with std::function for example):
void
myFunction(const std::function<void()/*type of your lamdba::operator()*/>& f)
{
//some things
}
You have two choices, basically.
Make it a template:
template<typename T>
void myFunction(T&& lambda){
}
or, if you do not want (or can't) do that, you can use type-erased std::function:
void myFunction(std::function<void()> const& lambda){
}
Conversely, your attempt with auto would've been correct under the concepts TS as currently implemented in gcc, where it'd be an abbreviated template.
// hypothetical C++2x code
void myFunction(auto&& lambda){
}
or with a concept:
// hypothetical C++2x code
void myFunction(Callable&& lambda){
}
A function that just wants to invoke a passed lambda or other functor during its own execution can be a function template, deducing the type of the functor:
template <typename F>
void use_it(F&& func) {
do_something_with(func());
}
Here you want to store the functor to be invoked later, so we'll need a common type that can wrap around various sorts of functors. This is what std::function is for. Assuming a return type of int:
#include <functional>
class MyObject {
// ...
private:
std::function<int()> mLambda;
};
void MyObject::SetXGetter(std::function<int()> func) {
mLambda = std::move(func);
}
Your call is missing the initial [captures] which is required for a lambda expression, even if nothing is captured:
myObject.SetXGetter([]{ return MyGlobals.GetX(); });
and I understand this is an area that has improved in more recent C++ versions?
Not in general. It has been expanded to some more complex cases, but the simple cases are pretty much identical to C++11.
Simplest way to pass a lambda as a method parameter in C++17
The options remain the same:
- You can have a template and pass the lambda as-is.
- Or you can wrap the lambda in a type erasing wrapper such as
std::functionin which case you can pass it into a non-template function. - Or if the lambda is non-capturing, then it can be converted to a function pointer which can also be passed into a non-template.
Which one is simplest can vary on context and personal opinion. Function wrapper works the same in widest number of different cases, to that's a simple choice. Function pointer doesn't involve dynamic allocation and is simplest to understand at a low level. Template doesn't involve any sort of wrapping or conversion, but it is a template.
this->mLambda = Lambda;
Given that you wish to store the callable as a modifiable member, storing it as a lambda is not an option. You're left with function wrapper and function pointer. You can still use a template for the function, but the lambda must be immediately wrapped or converted anyway, so there isn't much to be gained by using a template.
Basic version, for use in a header file:
template<typename Lambda>
bool Func1(int Arg1, Lambda Arg2){ // or Lambda&&, which is usually better
if(Arg1 > 0){
return Arg2(Arg1);
} else {
return false; // remember, all control paths must return a value
}
}
More complex version, if you want to split your interface from your implementation (it has run time costs):
bool Func1(int Arg1, std::function<bool(int)> Arg2){
if(Arg1 > 0){
return Arg2(Arg1);
} else {
return false; // remember, all control paths must return a value
}
}
std::function uses type erasure to create a custom-created wrapper around your lambda, and then exposes a non-virtual interface that uses the pImpl pattern to forward it to the custom-created wrapper.1
Or, in less technical terms, std::function<bool(int)> is a class that can wrap nearly anything that you can call like a function, passing one parameter that is compatible with passing an int, and it returns something that is compatible with returning a bool.
A call through a std::function has a run time cost roughly equal to a virtual function call (caused by the above type erasure), and when you create it it has to copy the state of the function object (aka functor) passed in (which can be cheap -- stateless lambdas, or lambdas capturing arguments by reference -- or expensive in some other cases) and store it (typically on the free store or heap, which has a cost), while the pure-template versions can be "inlined" at the point of call (ie, can not only cost less than a function call, the compiler can even optimize over the function call and return boundaries!)
If you want to split interface/implementation without all of the runtime costs of std::function, you can roll your own function_ref (in c++17, because that cuts down on some boilerplate):
template<class Sig>
struct function_ref;
template<class R, class...Args>
struct function_ref<R(Args...)> {
R operator()(Args...args) const {
return pf(state, std::forward<Args>(args)...);
}
function_ref()=default;
function_ref(function_ref const&)=default;
function_ref& operator=(function_ref const&)=default;
explicit operator bool()const{ return pf!=nullptr; }
// this overload reduces indirection by 1 step
// and allows function_ref<Sig> to resolve overloads
// on an overload set sometimes.
function_ref( R(*f)(Args...) ):
pf([](State const& state, Args&&...args)->R{
return reinterpret_cast<R(*)(Args...)>(state.pfunstate)(std::forward<Args>(args)...);
})
{
state.pfunstate = reinterpret_cast<void(*)()>(f);
}
// this grabs anything callable (that isn't this own type)
// and stores a pointer to it to call later.
template<class F>
requires (
std::is_convertible_v<
std::invoke_result_t< std::remove_reference_t<F>, Args... >, R
>
&& !std::is_same_v< std::decay_t<F>, function_ref >
)
function_ref( F&& f ):
pf([](State const& state, Args&&...args)->R{
return (*(std::remove_reference_t<F>*)state.pstate)(std::forward<Args>(args)...);
})
{
state.pstate = std::addressof(f);
}
private:
union State {
void* pstate = nullptr;
void(*pfunstate)();
};
State state;
R(*pf)(State const&, Args&&...) = nullptr;
};
// a deduction guide permitting function_ref{foo} to work
// if foo is a non-overloaded function name.
template<class R, class...Args>
function_ref( R(*)(Args...) )->function_ref<R(Args...)>;
Live example.
This removes the need to ever do any allocation from std::function by removing ownership semantics from it and just type-erasing calling.
A fancy version of the first example that also handles some corner cases a tad better: (also must be implemented within a header file, or in the same translation unit as it is used)
template<typename Lambda>
bool Func1(int Arg1, Lambda&& Arg2){
if(Arg1 > 0){
return std::forward<Lambda>(Arg2)(Arg1);
} else {
return false; // remember, all control paths must return a value
}
}
which uses a technique known as "perfect forwarding". For some functors, this generates slightly different behavior than #1 (and usually more correct behavior).
Most of the improvement comes form the use of && in the argument list: this means that a reference to the functor is passed in (instead of a copy), saving some costs, and allows both a const or non-const functor to be passed in.
The std::forward<Lambda>(...) change would only cause a change in behavior if someone used a relatively new C++ feature that allows methods (including operator()) to override on the rvalue/lvalue status of the this pointer. In theory, this could be useful, but the number of functors I've seen that actually override based on the rvalue status of this is 0. When I'm writing serious library code (tm) I go to this bother, but rarely otherwise.
There is one more possible thing to consider. Suppose you want to take either a function that returns bool, or a function that returns void, and if the function returns void you want to treat it as if it returned true. As an example, you are taking a function that is being called when iterating over some collection, and you want to optionally support early halting. The function returns false when it wants to stop prematurely, and true or void otherwise.
Or, in a more general case, if you have multiple overrides of a function, one of which takes a function and others take some other type at the same location.
This is possible, which is as far as I'm going to get into here (either with a smart adapter, or via SFINAE techniques). However, you are probably better off just creating two different named functions, because the techniques required are way too heavy weight.
1 Technically std::function could use magic fairy dust to do what it does, as its behavior is described by the standard, and not its implementation. I'm describing a simple implementation that approximates the behavior of the std::function implementation I have interacted with.
First solution:
You can make your Func1() function a function template:
template<typename T>
bool Func1(int Arg1, T&& Arg2){
if(Arg1 > 0){
return Arg2(Arg1);
}
return false; // <== DO NOT FORGET A return STATEMENT IN A VALUE-RETURNING
// FUNCTION, OR YOU WILL GET UNDEFINED BEHAVIOR IF FLOWING
// OFF THE END OF THE FUNCTION WITHOUT RETURNING ANYTHING
}
You could then invoke it as you desire:
int main()
{
Func1(12, [](int D) -> bool { return D < 0; } );
}
Second solution:
If you do not want to use templates, an alternative (that would bring some run-time overhead) is to use std::function:
#include <functional>
bool Func1(int Arg1, std::function<bool(int)> Arg2){
if(Arg1 > 0){
return Arg2(Arg1);
}
return false;
}
Once again, this would allow you to call Func1() the way you desire:
int main()
{
Func1(12, [](int D) -> bool { return D < 0; } );
}