lambda expression using scope variables - is safe? - c++

When f is called, a is already "destructed". Is it safe to use it this way? How does it work?
std::function<void()> f;
{
int a = some_calc();
f = [=] { std::cout << a << std::endl; }
}
f();

Is it safe to use it this way?
Yes
How does it work?
The closure object created by that lambda expression has int a as a data member, copy-initialised from the a in that scope.

Here is conceptually what is going on:
#include <functional>
#include <iostream>
int some_calc() {
// ...
return 42;
}
int main() {
std::function<void()> f;
{
int a = some_calc();
class Lambda {
private:
int a;
public:
Lambda(int const& _a) : a{_a} {}
void operator()() const { std::cout << a << std::endl; }
};
f = Lambda{a};
}
f();
}

Related

How to read the following code for main? I do not know this

How to read the following code for main?
I do not know this
Code :
class one
{
public:
void operator()() const
{
f();
f1();
}
};
I want to call the operator To main?
void operator()() const defines a function call operator, which can be used as:
one ob;
ob(); // calls ob.operator()()
For another, more complete, example.
#include <iostream>
class Two
{
public:
int operator()(const char *str) const
{
std::cout << "operator() called with " << str << std::endl;
return 101;
}
};
int main()
{
Two two;
int n = two("'test'");
std::cout << "operator() returned " << n << std::endl;
}
Output:
operator() called with 'test'
operator() returned 101
You can create an instance of the class in the main function and call the function using that instance.
class one
{
public:
void operator()() const
{
f();
f1();
}
};
int main() {
one obj_one;
// calling the member function -> method
obj_one.operator()();
return 0;
}

How to pass function of one class as argument of another function of another class

I have created a class Base which has a function addSuccessor() that takes address of function as argument and stores it in successor. How do I pass a function of another object in addSuccessor().
Here is my program. I think my main() has some mistake.
#include <iostream>
#include<vector>
using namespace std;
class Base{
public:
void (*successor)()=NULL;
void addSuccessor ( void (*f)() )
{
successor=f;
}
void start()
{
cout<<"In Class"<<endl;
if(!successor==NULL)
successor();
else
cout<<"No Successor"<<endl;
}
};
class Second{
public:
void foo()
{
cout<<"Successor";
}
};
int main()
{
Base obj;
Second obj2;
obj.addSuccessor(&obj2.foo());
obj.start();
}
Function pointers are very limited. Use a std::function (defined in header <functional>) instead, which can store any invocable object in a type-erased manner, and provide a template member function to set the functor in which perfect forwarding is used to forward the provided functor to successor: (std::forward is defined in header <utility>)
class Base {
std::function<void()> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
successor();
} else {
std::cout << "No Successor\n";
}
}
};
Then, you can pass a lambda expression to add_successor:
obj.add_successor([&]{ obj2.foo(); });
(live demo)
As a complement to the discussion above (based on #L.F.'s answer):
#include <functional>
#include <iostream>
#include <utility>
class Base {
std::function<int(int)> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
auto z = std::invoke(successor, 100);
std::cout << "Output = " << z << "\n";
} else {
std::cout << "No Successor\n";
}
}
};
class Second {
public:
int foo(int x)
{
auto y = x + x;
std::cout << "Successor\n";
return y;
}
};
int main()
{
Base obj;
Second obj2;
obj.add_successor([&](int x)->int { return obj2.foo(x); });
obj.start();
}

How to create a map of <id, member function>?

I have the following code in which I create a map of pointers to member functions.
class A {
public:
A() {
m[0] = &A::F1;
m[1] = &A::F2;
}
void F1(int v) { ... }
void F2(int v) { ... }
void O(int i, int v) {
(*m[i])(v);
}
private:
using func = void(A::*)(int);
std::map<int, func> m;
};
But there is a compiling error in "O". In my understanding, "m[i]" is a pointer to member function, (*m[i]) dereferences it and should call the corresponding member function. But it does not work.
Could you please help to explain it?
Are there other neat ways to create a map of member functions?
The pointer to a member function only holds the pointer to the function, but not to the object on which it should be called.
You need to call that member function on an object:
(this->*m[i])(v);
Another way you could accomplish the same (arguably easier to read than plain function pointers) is with std::function, example:
class A {
public:
A() { // implicit capture of this is deprecated in c++20
m[0] = [this](int v) { F1(v); };
m[1] = [this](int v) { F2(v); };
}
void F1(int v) { std::cout << "F1: " << v; }
void F2(int v) { std::cout << "F2: " << v; }
void O (int i, int v) { m[i](v); }
private:
std::map<int, std::function<void(int)>> m;
};
int main() {
A a;
a.O(0, 5);
}

Can i use C++ function pointers like a C#'s Action?

In C ++, I first encountered function pointers.
I tried to use this to make it similar to Action and Delegate in C #.
However, when declaring a function pointer, it is necessary to specify the type of the class in which the function exists.
ex) void (A :: * F) ();
Can I use a function pointer that can store a member function of any class?
In general, function pointers are used as shown in the code below.
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(A::*BF)();
};
int main()
{
A a;
B b;
b.BF = &A::AF;
(a.*b.BF)();
return 0;
}
I want to use it like the code below.
is this possible?
Or is there something else to replace the function pointer?
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(* BF)();
};
int main()
{
A a;
B b;
b.BF = a.AF;
return 0;
}
I solved the question through the answer.
Thanks!
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class C {
public:
void CF() { std::cout << "C::F" << std::endl; }
};
class B {
public:
B(){}
std::function<void()> BF;
};
int main() {
A a;
C c;
B b;
b.BF = std::bind(&A::AF, &a);
b.BF();
b.BF = std::bind(&C::CF, &c);
b.BF();
int i;
std::cin >> i;
return 0;
}
What you want to do is probably something like this. You can use std::function to hold a pointer to a member function bound to a specific instance.
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class B {
public:
B(const std::function<void()>& bf) : BF(bf) {}
std::function<void()> BF;
};
int main() {
A a;
B b1(std::bind(&A::AF, &a)); // using std::bind
B b2([&a] { a.AF(); }); // using a lambda
b1.BF();
b2.BF();
return 0;
}
Here's a C# style implementation of the accepted answer, It is memory efficient and flexible as you can construct and delegate at different points of execution which a C# developer might expect to do:
#include <iostream>
#include <functional>
using namespace std;
class A {
public:
void AF() { cout << "A::F" << endl; }
void BF() { cout << "B::F" << endl; }
};
class B {
public:
std::function<void()> Delegate;
};
int main() {
A a;
B b;
b.Delegate = std::bind(&A::AF, &a);
b.Delegate();
b.Delegate = [&a] { a.BF(); };
b.Delegate();
return 0;
}

C++ Retaining a Lambda Expression in an Object

Okay, so I'm writing a simple GUI framework. I stumbled across lambda expressions and thought they'd be a good way to do callbacks. But I can't figure out how to retain the expression in class (very simplified example code below).
class class1
{
public:
class1(auto callback);
private:
const auto mCallback
};
class1::class1(auto callback) : mCallback(callback)
{
}
int main()
{
auto thiscode = [] (int id)
{
std::cout<<"callback from..." << id << std::endl;
};
class1 c1 = class1(thiscode);
}
I end up with this error,
error: non-static data member declared 'auto'
Which I suppose makes sense, it can't determine the size at run time. In fact, below C++14 it won't even allow me to pass auto callback as a paramter to the constructor. (I think that changed in a readying process for concepts?).
How do I get around this? I don't mind having to do something weird, anything that allows me to retain a reference to the passed lambda expression - I'm golden with.
You can use std::function to store thiscode.
Something like this:
#include <functional>
#include <iostream>
class class1 {
public:
class1(std::function<void(int)> callback) : mCallback{callback} {};
void do_callback() { mCallback(3); };
private:
const std::function<void(int)> mCallback;
};
int main()
{
auto thiscode = [](int id) {
std::cout<<"callback from..." << id << std::endl;
};
class1 c1 = class1(thiscode);
c1.do_callback();
return 0;
}
See live demo here.
You can hold them with templates
template<typename T>
class class1
{
public:
class1(T callback): mCallback{std::move(callback)} {}
private:
const T mCallback
};
template<typename T>
auto makeClass1(T&& callback) {
return class1<std::decay_t<T>>{std::forward<T>(callback)};
}
int main()
{
auto thiscode = [] (int id)
{
std::cout<<"callback from..." << id << std::endl;
};
auto c1 = makeClass1(thiscode);
}
Or alternatively, you can hold them with std::function:
class class1
{
public:
class1(std::function<void(int)> callback);
private:
const std::function<void(int)> mCallback
};
int main()
{
auto thiscode = [] (int id)
{
std::cout<<"callback from..." << id << std::endl;
};
class1 c1 = class1(thiscode);
}