Does std::function keeps a reference to captured variables [duplicate] - c++

This question already has answers here:
C++11 lambda implementation and memory model
(2 answers)
What is a lambda expression in C++11?
(10 answers)
Closed 2 years ago.
I'd like to understand why the following works:
class Foo {
public:
using Callback = std::function<void(std::string& string)>;
void setCallback(Callback&& callback) { windowInfo = callback; };
private:
Callback windowInfo;
};
class Bar {
Bar() { foo->setCallback([this](std::string& e) { sayHello(e); });}
void sayHello(std::string& name) { //do something }
Foo* foo;
};
Foo::setCallback asks for a function with no captures, however, I'm passing a lambda that captures Bar. I would expect the compiler to complain void(Bar, string) != void(string). Since I'm passing in a member function, it must implicitly pass the $this parameter as the first argument. Making the function signatures not equivalent.
EDIT
Why is that when I redefine using EventCallback as using EventCallback = void(Event& event); suddently this doesn't work anymore "no viable conversion from Application.cpp:10:34 to Foo::Callback aka (...)
Is std::function acting as the "glue" holding a reference to Bar but exposing the correct signature when requested?

Related

how to get the class member variable before arrow operator in c++ [duplicate]

This question already has an answer here:
Pass a member function as argument error: "reference to non-static member function must be called"
(1 answer)
Closed 7 months ago.
This post was edited and submitted for review 7 months ago and failed to reopen the post:
Original close reason(s) were not resolved
This may kind of odd but I do have this case in my job.
Say I have a function:
A->fucntion();
And this function will be passed as a parameter to another function
(func(A->function);)
My question is how to get variable A in the func()?
I am new to c++, thank you for any advice!
2 relevant issues:
You will need to pass your instance (A) as an additional parameter.
Without it you will not be able to invoke a pointer-to-member.
You will also need to use the syntax to invoke a method via a pointer-to-member.
See a complete example:
(used A for the class name and a for the instance, as it's more common)
#include <iostream>
struct A
{
void function()
{
std::cout << "A::function()" << std::endl;
}
};
// Type of a pointer to a method of class A:
typedef void (A::* AsMethod)();
//--------vvvv------------------- (add parameter for the instance)
void func(A& a, AsMethod aMethod)
{
// Invoke a method via pointer-to-member:
(a.*aMethod)();
}
int main()
{
A a;
//-------v---------------- ) (pass the instance)
func(a, &A::function);
}
Output:
A::function()

How to make a callback in C++: use a class member function as a parameter [duplicate]

This question already has answers here:
Callback functions in C++
(11 answers)
Closed 2 years ago.
I started using C++ recently and at one point I needed to set up a callback, i.e. call a function of another class and pass to it as a parameter the name of one of my own functions so that it calls it back. At first I tried this:
void myOtherFunction(void (*oneOfMyFunctions)(void)) {
oneOfMyFunctions();
}
Unfortunately this code doesn't support class member functions because it is (correct me if I am wrong) ...C code.
This can work.
void myOtherFunction(void (*oneOfMyFunctions)(void)) {
oneOfMyFunctions();
}
However, your problem may be due to trying to pass member functions into this function. If member_function is a member function of class A, the expression &member_function inside class A has a type of void (A::*)(void), not void (*)(void) like you want (that is, it wants an A pointer in addition to its normal parameters). You can use std::bind():
std::bind(&member_function, this)
to create a function object which can be called with an empty parameter list. However, then you would need to change your member function signature to something like this:
template <typename FuncType>
void myOtherFunction(FuncType oneOfMyFunctions) {
oneOfMyFunctions();
}
or, like Th0rgal may have said,
void myOtherFunction(std::function<void()> oneOfMyFunctions) {
oneOfMyFunctions();
}
Here is a working way to do that:
void myOtherFunction(std::function<void()> oneOfMyFunctions) {
oneOfMyFunctions();
}
And inside my class:
myOtherFunction([&] {
oneOfMyFunctions();
});
Some explanations:
In std::function<void()>, void is what is returned by the function and () contains the types of its parameters (mine is empty because it doesn't have any).
In the 2nd code I am using a lambda to keep the context, as a bind would do (but lambdas replace them).

What is the proper way to pass lambda as an argument in C++ [duplicate]

This question already has answers here:
passing lambda as argument - by reference or value?
(2 answers)
Proper way to receive a lambda as parameter by reference
(5 answers)
Closed 4 years ago.
As far as I know, I have at least the following three ways to declare a function which accept closures:
by copying
by reference
by moving
e.g.
void FooCopyLambda(std::function<void()> f) {
// ...
f();
// ...
}
void FooRefLambda(const std::function<void()> &f) {
// ...
f();
// ...
}
void FooMoveLambda(std::function<void()> &&f) {
// ...
f();
// ...
}
In This question, people discussed how to pass by reference. But here I also want to know, should I pass it by reference? Or maybe I should pass it by value or moving?
What's the proper way to pass lambda as an argument? Why?

Passing non-static member function as std::function [duplicate]

This question already has answers here:
Using generic std::function objects with member functions in one class
(6 answers)
Closed 4 years ago.
I have a similar situation:
class A {
void callingFunction() {
calledFunction(passedFunction);
}
void calledFunction(std::function<void(int)> foo) {
}
void passedFunction(int arguments) {
}
};
The compiler error is
error: invalid use of non-static member function
How do I achieve this without making the passedFunction static?
Doing this:
calledFunction(std::bind(&A::passedFunction, this);
Creates this error:
error:static assertion failed: Wrong number of arguments foor pointer-to-member
Does it mean I have to provide all the arguments in the callingFunctionwhen passing the passedFunction? This is not possible as the arguments for the passedFunction are specified in the calledFunction
You can write a lambda capturing this, on which passedFunction could be called.
calledFunction([this](int v) { this->passedFunction(v); });

Vector of member functions [duplicate]

This question already has answers here:
Using generic std::function objects with member functions in one class
(6 answers)
Closed 5 years ago.
What is the approach to have a vector to schedule method calls of a class. I would like to have a vector of methods, something like this:
class Model {
using task_t = std::function<void()>;
std::vector<std::vector<task_t>> _frameTasks;
void add_function() { _frameTasks[3].push_back(&(this->function()); }
void function() {std::cout << "hi"; }
void step() {
for (auto task : _frameTasks[3]) task();
}
}
But the compiler complains that:
error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.
How could I solve this issue or what is the right approach?
&(this->function()) is applying & to the result of the call to the function() member function. The default operator& requires an lvalue, however, the expression this->function() is not an lvalue.
Writing &Model::function won't work either because it is a pointer to a member function (as opposed to a pointer to a function). Its type is void (Model::*)(), i.e.: a pointer to a Model's (non-static) member function that takes no parameters and returns nothing.
You need some way to specify the Model object on which the function() member function will be called.
Since C++11 you can achieve that by simply using a lambda expression:
void add_function() {
_frameTasks[3].push_back(
[this](){ add_function(); }
);
}