Can lambda be reused?
I'd like to call this lambda a few times. But I can't find a way to give it a name.
[]() { cout << "lambda is called"; };
And what is the purpose of lambda without invoking like this? Compiler does not yell at the code above, but it is useless. Am I right?
You can give it a name using the auto specifier:
auto f = []() { cout << "lambda is called"; };
That will allow you to invoke it with f(). But bear in mind that the type of a lambda isn't specified, so if you want to pass it to functions, you'll need to use templates (or convert to std::function<void()>).
template <typename F>
void three_times(F g) {
g(); g(); g();
}
If you want to reuse a lambda you need to assign it to a variable.
auto lambda = []() { cout << "lambda is called"; };
gives you an object named lambda that you can call the operator () on to execute the body of the lambda like
lambda();
Yes lamda can be reused. See the example below
#include <iostream>
using namespace std;
template <typename F> void func2(F f) {
f("func2");
}
void func(function<void(const char *)> f) {
f("func");
}
int main() {
auto l = [](const char *s) {
cout << s << "\n";
};
for (int i = 0; i < 2; i++) {
l("main"); // Calling lambda multiple times
func(l); // Passing lambda to a function using function<>
func2(l); // Passing lambda to a function using template
}
return 0;
}
Output:
main
func
func2
main
func
func2
You can easily give a lambda a name by assigning it to an auto variable - like so;
const auto l = [] { whatever };
Then call l multiple times as l(); .
Store the lambda using auto
or assign it to a compatible std::function explicitly:
auto f1 = [](int x, int y)->float{ ..... };
std::function<float(int,int)> f2 = [](int x, int y)->float{ ..... };
float x = f1(3,4);
auto y = f2(5,6);
std::function<float(int,int)> f3 = f1;
Related
Here is simple example of using std::function
#include <iostream>
#include <functional>
//A function that sums two numbers.
//Arguments having default values.
void SumOfTwoNumbers(int a = 42, int b = 42)
{
std::cout << "Sum of two numbers :: " << a + b << std::endl;
}
int main()
{
std::function<void(int, int)> testFunc = SumOfTwoNumbers;
SumOfTwoNumbers(); //Works
testFunc(); //Compile time error
testFunc(40, 40); //Works
return 0;
}
In the main function, there are three function calls. The first one and the last one works. Whereas the second call testFunc() without any arguments gives compile time error.
Shouldn't it consider the default arguments and execute successfully?
No, the default values for function arguments are not part of the function signature. They are evaluated at the call site only.
You could use a lambda but then you'd need to redefine the default values:
auto testFunc = [](int a = 42, int b = 42) { SumOfTwoNumbers(a, b); };
... and storing such a lambda in a std::function would again result in the same problem since the signature of the lambda is also void(int, int).
You could however define your own wrapper functor (instead of using std::function) that has multiple operator() overloads:
struct {
void operator()() { SumOfTwoNumbers(42, 42); }
void operator()(int a) { SumOfTwoNumbers(a, 42); }
void operator()(int a, int b) { SumOfTwoNumbers(a, b); }
} testFunc;
typedef void (*voidfunc)();
void somefunc(voidfunc function)
{
voidfunc func = function;
struct wrapper
{
function(); //does not work
func(); //does not work
};
}
Is there any way at all to access function from inside the struct wrapper? I am trying to see if it is possible to implement python style wrapper. Something like a timer. Where somefunc takes a function, wrapper runs that function and timers it.
Something like this ?
wrapper_struct_type timer(voidfunc function)
{
struct wrapper
{
void timeit()
{
//start time
function(); //does not work
//endtime
//time = end- start
}
};
//return wrapper
}
Working example in python
import time
def timer(func):
def wrapper():
start = time.time()
func()
end = time.time()
print(end - start)
return wrapper
#timer
def somefunc():
print("hello world")
somefunc()
Lambda Solution
You can achieve this using C++ lambdas.
Note my example requires C++14 (or greater) to compile.
#include <iostream>
typedef void (*voidfunc)();
void doNothing() {}
auto foo(voidfunc function)
{
auto wrapper = [function]()
{
int x = 1;
function();
int y = 1;
std::cout << y - x << "\n";
};
return wrapper;
}
int main()
{
auto fn = foo(doNothing);
fn();
foo(doNothing)();
return 0;
}
In the foo function, the function passed to foo is "captured" for use in the lambda's body. Then, the function is executed in the body of the lambda. At the end of the body of foo, the lambda is returned.
Then the main function demonstrates how the foo function can be used. A voidfunc can be passed to foo, and then the returned lambda can be assigned to a variable (in my example it is assigned to fn). Then the returned lambda can be invoked (in my example it is invoked with fn()). Or, the returned lambda can be invoked directly, without using a variable (in my example I do this with foo(doNothing)();).
I use int x and int y as examples since I do not know what precision you might be looking for for time deltas.
Lambda-free Solution
Here is an alternate (and, in my opinion, less elegant) solution that works if lambdas are not supported for the C++ compiler/standard you are compiling with:
#include <iostream>
typedef void (*voidfunc)();
struct Foo
{
voidfunc function;
Foo(voidfunc fn) : function(fn) {}
void wrapper()
{
int x = 1;
function();
int y = 1;
std::cout << y - x << "\n";
}
};
void doNothing() {}
int main()
{
Foo foo(doNothing);
foo.wrapper();
return 0;
}
Here, there is a Foo struct that is passed a voidfunc function via its constructor. The voidfunc is then stored as the function member of the Foo struct (function could be declared as private if desired).
In main in my example, a Foo is created as foo. Then, whenever the wrapper function is executed on foo, the function stored in foo will be executed.
You could create a struct and overload the call operator. The struct will take a std::function<void()> in its constructor. Then simply call the instance of the struct.
std::function gives you type erasure. So as long you have any callable that has the right signature, it will provide a wrapper around it.
#include <iostream>
#include <functional>
#include <chrono>
struct timerit
{
timerit(std::function<void()> fn) : mFunction{fn} {}
void operator()() const
{
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
mFunction();
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
auto dur = end - start;
auto milli = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
std::cout << milli.count() << "ms" << std::endl;
}
std::function<void()> mFunction;
};
void count()
{
for(int i=0; i<1000000; ++i);
}
int main()
{
auto lambda = []() { for(int i=0; i<1000000; ++i); };
timerit t1{lambda}; //lambda
t1();
timerit t2{count}; //function
t2();
return 0;
}
Live demo
Note that you also do this:
timerit{lambda}();
which will invoke the call operator immediately without giving you an variable of type timerit.
You can provide your own implementation inside the call operator and call the function object that you pass in. My implementation sticks closely to the timer example that you provided in your question.
I'm trying to figure out how to get the address of a lambda function within itself. Here is a sample code:
[]() {
std::cout << "Address of this lambda function is => " << ????
}();
I know that I can capture the lambda in a variable and print the address, but I want to do it in place when this anonymous function is executing.
Is there a simpler way to do so?
There is no way to directly get the address of a lambda object within a lambda prior to c++23.
Now, as it happens this is quite often useful. The most common use is in order to recurse.
The y_combinator comes from languages where you could not talk about yourself until you where defined. It can be implemented pretty easily in c++:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( f, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( f, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator(F)->y_combinator<F>;
now you can do this:
y_combinator{ [](auto& self)-> void {
std::cout<<"Address of this lambda function is => "<< &self;
} }();
There are a few useful variations. One variation I find particularly useful is:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( *this, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( *this, std::forward<Args>(args)... );
}
};
where the self passed can be called without passing in self as the first argument.
The second matches the real y combinator (aka the fixed point combinator) I believe. Which you want depends on what you mean by 'address of lambda'.
There is also this pithy one:
template<class R, class...Args>
auto Y = [] (auto f) {
auto action = [=] (auto action) -> std::function<R(Args...)> {
return [=] (Args&&... args)->R {
return f( action(action), std::forward<Args>(args)... );
};
};
return action(action);
};
which returns a std function.
In c++23 accessing this within a lambda gets easier:
auto fib = [](this auto& self, int n) {
if (n < 2) return n;
return self(n-1) + self(n-2);
};
you can tag the first argument as this, and it becomes itself. It even works with the overload set trick, where self is the most-deduced type.
It is not directly possible.
However, lambda captures are classes and the address of an object coincides with the address of its first member. Hence, if you capture one object by value as the first capture, the address of the first capture corresponds to the address of the lambda object:
int main() {
int i = 0;
auto f = [i]() { printf("%p\n", &i); };
f();
printf("%p\n", &f);
}
Outputs:
0x7ffe8b80d820
0x7ffe8b80d820
Alternatively, you can create a decorator design pattern lambda that passes the reference to the lambda capture into its call operator:
template<class F>
auto decorate(F f) {
return [f](auto&&... args) mutable {
f(f, std::forward<decltype(args)>(args)...);
};
}
int main() {
auto f = decorate([](auto& that) { printf("%p\n", &that); });
f();
}
One way to solve this, would be to replace the lambda with a hand written functor class. It's also what the lambda essentially is under the hood.
Then you can get the address through this, even without ever assigning the functor to a variable:
#include <iostream>
class Functor
{
public:
void operator()() {
std::cout << "Address of this functor is => " << this;
}
};
int main()
{
Functor()();
return 0;
}
Output:
Address of this functor is => 0x7ffd4cd3a4df
This has the advantage that this is 100% portable, and extremely easy to reason about and understand.
Capture the lambda:
std::function<void ()> fn = [&fn]() {
std::cout << "My lambda is " << &fn << std::endl;
}
It is possible but highly depends on the platform and compiler optimization.
On most of the architectures I know, there is register called instruction pointer. The point of this solution is to extract it when we are inside the function.
On amd64 Following code should give you addresses close to the function one.
#include <iostream>
void* foo() {
void* n;
asm volatile("lea 0(%%rip), %%rax"
: "=a" (n));
return n;
}
auto boo = [](){
void* n;
asm volatile("lea 0(%%rip), %%rax"
: "=a" (n));
return n;
};
int main() {
std::cout<<"foo"<<'\n'<<((void*)&foo)<<'\n'<<foo()<<std::endl;
std::cout<<"boo"<<'\n'<<((void*)&boo)<<'\n'<<boo()<<std::endl;
}
But for example on gcc https://godbolt.org/z/dQXmHm with -O3 optimization level function might be inlined.
I am using c++14 and I have a use case where I have to effectively do this:
template <typename F>
void foo (F&& fun)
{
auto l = []()->int
{
return 20;
};
fun(l);
}
int main ()
{
auto l = [] (auto& a)
{
std::cout << "Hello function: " << a() << std::endl;
// 'a' has to be copied to a queue optionally
};
foo(l);
}
But the foo() in-turn calls a million function - which uses the callback 'fun'. I cannot put all the code in header file. The simplest way to keep the definition of foo() and the called functions in dot cpp file might be to change foo() to
void foo (std::function< void(std::function<int(void)>) > fun)
But this is too inefficient, I dont want any memory allocation. Here there will be many, one of the creating the 'fun' and then for every call to 'fun(...)'. Now the outer std::function can be optimized by using something like the function_ref mentioned here.
https://vittorioromeo.info/index/blog/passing_functions_to_functions.html#fn_view_impl
But inner std::function, cannot be because it has to be 'optionally' copied to a queue. Now how can I make this work without a memory allocation - as close to the performance as using the template. [ One way is to have something like the std::function with a fixed internal storage.] But I have a feeling there exists a way by throwing more templates to achieve what I want. Or some way to change the interface to have more of less same effect.
Not sure if this is what you're looking for, but maybe it can be to some help.
#include <iostream>
#include <deque>
#include <memory>
struct lambdaHolderBase {
virtual int operator()() = 0;
};
template <typename T>
struct lambdaHolder : lambdaHolderBase {
lambdaHolder(T tf) : t(tf) {}
T& t;
int operator()() override { return t(); }
};
template <typename F>
void foo (F&& fun)
{
auto l = []()->int
{
return 20;
};
lambdaHolder<decltype(l)> l2(l);
fun(l2);
}
int main ()
{
auto l = [] (auto& a)
{
static std::deque<lambdaHolderBase*> queue;
std::cout << "Hello function: " << a() << std::endl;
queue.emplace_back( &a );
// 'a' has to be copied to a queue optionally
};
foo(l);
}
I'm trying to add a line of code to the end of a lambda, similar to what the += operator does to std::string. For instance:
std::function<void()> foo = []() {
std::cout << "User defined code\n";
};
foo += [](){ std::cout << "I added this"; };
Desired output after calling foo():
User defined code
I added this
Of course this does not actually work as written.
Is this possible, or is there another way to effectively accomplish the same thing? Perhaps copying the lambda to another std::function then pass by value to a new lambda or something?
Edit:
I'm working with a class with a std::function member (foo) initialized with a lambda. Its member functions call it directly (with foo()) and I need to make it so that every time foo is called, an additional function is called as well. However this can be done would be great, as long as foo can still be called with foo();.
If you can change the type of the member, something like this might do it:
class Functions
{
public:
using Function = std::function<void()>;
Functions() = default;
template<typename Fn>
Functions(Fn f) { functions.push_back(f); }
Functions& operator+=(Function f)
{
functions.push_back(f);
return *this;
}
void operator()()
{
for (auto& f: functions)
{
f();
}
}
private:
std::vector<Function> functions;
};
Functions foo = []() { cout << "Hello"; }
foo += []() { cout << ", world!"; };
foo();
This solution is the closest I could come up with for your problem at hand:
class Lambdas
{
vector<function<void()>> lambdas;
public:
Lambdas(function<void()> lamb)
{
lambdas.push_back(lamb);
}
Lambdas& operator+=(function<void()> lamb)
{
lambdas.push_back(lamb);
return *this;
}
void operator()()
{
for (int i = 0; i<lambdas.size(); i++)
{
lambdas[i]();
}
}
};
Hope this helps.