When to use this for class function in lambda - c++

When should this be used in a lambda to call a class member function? I have an example below, where hello(); is called without this but this->goodbye(); does:
#include <iostream>
class A
{
void hello() { std::cout << "hello" << std::endl; }
void goodbye() { std::cout << "goodbye" << std::endl; }
public:
void greet()
{
auto hi = [this] () { hello(); }; // Don't need this.
auto bye = [this] () { this->goodbye(); }; // Using this.
hi();
bye();
}
};
int main()
{
A a;
a.greet();
return 0;
}
Is there any advantage to one way over the other?
Edit: The lambda for hello does not capture anything, yet it inherits functions that exist in the class scope. It cannot do this for members, why can it do this for functions?

this is more explicit and more verbose.
but it might be also required with variables which hide member (capture or argument):
auto goodbye = [](){}; // Hide method
auto bye = [=] (int hello) {
this->goodbye(); // call method
goodbye(); // call above lambda.
this->hello(); // call method
std::cout << 2 * hello; // show int parameter.
};

Related

callback in C++ struct

I have been trying to implement a callback function in c++. Within a class, I have a struct, a number of methods, and a method that creates an instance of the struct with one of the other methods as its argument.
The struct has many other variables, but an illustration is depicted here:
class MYCLASS
{
public:
MYCLASS();
struct TEST{
std::function<int(int)> foo;
};
int plus(int x){
return x + 1;
}
int minus(int x){
return x - 1;
}
void sim(){
TEST T; // make an instance of TEST
T.foo = plus(5); // assign TEST.foo a function (plus or minus)
T.foo(); // call the method we assigned
}
};
Within the sim method, I want to create an instance of test and give it either plus or minus, depending on some criterion. Both lines where I try and give the instance T a plus function and subsequently call it are incorrect.
If you want to delay the call to T.foo, then you could use a lambda like this:
T.foo = [this](int x) { return plus(x); };
T.foo(5);
Option - 1
If the member functions plus() and minus() are simple enough like you have shown, you can make them as lambda functions inside the struct TEST.
Since the capture-less lambdas can be stored in typed function pointers, the following will do what you want.
See live demo
#include <iostream>
class MYCLASS
{
int m_var = 5; // just for demonstration
public:
MYCLASS() = default;
struct TEST
{
using fPtrType = int(*)(int); // function pointer type
const fPtrType foo1 = [](int x) { return x + 1; }; // plus function
const fPtrType foo2 = [](int x) { return x - 1; }; // minus function
};
void sim()
{
TEST T;
std::cout << "Answer from int PLUS(int): " << T.foo1(m_var) << std::endl;
std::cout << "Answer from int MINUS(int): " << T.foo2(m_var) << std::endl;
}
};
Option - 2
If the above alter a lot in your code, use typed function pointer again for member functions and do as follows; which will avoid unnecessary copying(by capturing) the class instance to the lambda and template instantiation and other performance issues comes along with std::function as well.
See live demo
#include <iostream>
class MYCLASS
{
using fPtrType = int(MYCLASS::*)(int); // class member function pointer type
public:
MYCLASS() = default;
struct TEST { fPtrType foo = nullptr; };
int plus(int x) { return x + 1; }
int minus(int x) { return x - 1; }
void sim()
{
TEST T;
T.foo = &MYCLASS::plus; // now you can
std::cout << "Answer from int PLUS(int): " << (this->*T.MYCLASS::TEST::foo)(5) << std::endl;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ syntax would be a bit ugly
// later same ptr variable for minus()
T.foo = &MYCLASS::minus;
int answer = (this->*T.MYCLASS::TEST::foo)(5);
std::cout << "Answer from int MINUS(int): " << answer << std::endl;
}
};
int main()
{
MYCLASS obj;
obj.sim();
return 0;
}
Output:
Answer from int PLUS(int): 6
Answer from int MINUS(int): 4

How to call a C++ class method, which is given as a parameter?

I'm trying to pass a method as a parameter to other method.
Magner.h:
Class Manager{
public:
timeCount(void (Manger::*function)(void));
void passedFuction();
}
In Manager.cpp, I'm trying to call timeCount by
timeCount(&Manager::passedFuction());
TimeCount Body:
void Manager::timeCount(void(Manager::*function)(void))
{
std::cout << "It works";
(*function)(); // here is error
}
ViusalStudio says:
void*Manager::*function)() operand of '*' must be a pointer
How should i correct it?
The example i was learing by was : http://www.cplusplus.com/forum/beginner/6596/
A pointer-to-member-function (pmf) is not a pointer. Let me repeat that:
A pointer-to-member-function is not a pointer.
To call a pmf, you have to provide it with the object you want to call it on. You probably want:
(this->*function)();
If you had another object obj of the right type, you could also use:
(obj.*function)();
The void (Manger::*function)(void) syntax is for member functions of Manager class, which cannot be used with functions outside the Manager class.
To fix this shortcoming, pass std::function<void(void)> instead, which would let you invoke itself using the regular function invocation syntax:
void Manager::timeCount(std::function<void(void)> f) {
std::cout << "It works";
f();
}
Here is a complete demo of how to call timeCount with member and non-member functions:
struct Manager {
string name;
void timeCount(std::function<void(void)> f) {
std::cout << "This is " << name << " manager" << endl;
f();
}
};
void foo() {
cout << "I'm foo" << endl;
}
struct Test {
int x;
void bar() {
cout << "I'm bar " << x << endl;
}
};
int main() {
Manager mgr {"time"};
mgr.timeCount(foo);
Test tst = {234};
mgr.timeCount(std::bind( &Test::bar, tst));
return 0;
}
Demo.
Since c++17, we have std::invoke:
std::invoke(function, this);
or
std::invoke(function, *this);
are both ok. Minimal demo:
#include <functional>
#include <iostream>
class Manager
{
public:
void timeCount(void (Manager::*function)(void));
void passedFuction()
{
std::cout << "call passedFunction\n";
}
};
void Manager::timeCount(void (Manager::*function)(void))
{
std::cout << "It works\n";
std::invoke(function, *this);
// (*function)(); // here is error
}
int main()
{
Manager a;
a.timeCount(&Manager::passedFuction);
}
It works
call passedFunction
live demo

C++ Add to the end of a lambda

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.

C++11 styled callbacks?

I have a void function inside of a class. In old C++ i'd make a function static taking the class name as a parameter and had my own class which took a static void function + a void* for me to easily call it.
However that feels old school. It also isn't templated which feels like i could be doing more. What is a more modern way of creating callbacks to myclassVar.voidReturnVoidParamFunc
Use std::function and lambdas (or std::bind()) to store callables:
#include <functional>
#include <iostream>
class Test
{
public:
void blah() { std::cout << "BLAH!" << std::endl; }
};
class Bim
{
public:
void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }
int main()
{
// store the member function of an object:
Test test;
std::function< void() > callback = std::bind( &Test::blah, test );
callback();
// store a callable object (by copy)
callback = Bim{};
callback();
// store the address of a static function
callback = &boum;
callback();
// store a copy of a lambda (that is a callable object)
callback = [&]{ test.blah(); }; // often clearer -and not more expensive- than std::bind()
callback();
}
Result:
BLAH!
BIM!
BOUM!
BLAH!
Compiles and run: http://ideone.com/T6wVp
std::function can be used as any copyiable object, so feel free to store it somewhere as a callback, like in object's member. It also means that you can freely put it in standard containers, like std::vector< std::function< void () > > .
Also note that equivalent boost::function and boost::bind have been available for years.
For an example of passing in parameters to a C++ 11 callback using Lambda's and a vector, see http://ideone.com/tcBCeO or below:
class Test
{
public:
Test (int testType) : m_testType(testType) {};
void blah() { std::cout << "BLAH! " << m_testType << std::endl; }
void blahWithParmeter(std::string p) { std::cout << "BLAH1! Parameter=" << p << std::endl; }
void blahWithParmeter2(std::string p) { std::cout << "BLAH2! Parameter=" << p << std::endl; }
private:
int m_testType;
};
class Bim
{
public:
void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }
int main()
{
// store the member function of an object:
Test test(7);
//std::function< void() > callback = std::bind( &Test::blah, test );
std::function< void() > callback = std::bind( &Test::blah, test );
callback();
// store a callable object (by copy)
callback = Bim{};
callback();
// store the address of a static function
callback = &boum;
callback();
// store a copy of a lambda (that is a callable object)
callback = [&]{ test.blah(); }; // might be clearer than calling std::bind()
callback();
// example of callback with parameter using a vector
typedef std::function<void(std::string&)> TstringCallback;
std::vector <TstringCallback> callbackListStringParms;
callbackListStringParms.push_back( [&] (const std::string& tag) { test.blahWithParmeter(tag); });
callbackListStringParms.push_back( [&] (const std::string& tag) { test.blahWithParmeter2(tag); });
std::string parm1 = "parm1";
std::string parm2 = "parm2";
int i = 0;
for (auto cb : callbackListStringParms )
{
++i;
if (i == 1)
cb(parm1);
else
cb(parm2);
}
}

Rebinding lambda in c++11... is it possible?

I have a situation where I have a lambda as a member variable that is created by a certain function call. The problem is that it captures this as a part of its operation. Later on, I want to be able to copy the whole object...
However, at the time of the copy I don't know how the lambda was created (it could have been defined in several spots through different code paths). Hence, I'm somewhat at a loss as to what to put in the copy constructor. Ideally, I would want to "rebind" the lambda's captures to the new "this" that was created.
Is this at all possible?
Here's some sample code:
#include <iostream>
#include <string>
#include <functional>
class Foo
{
public:
Foo () = default;
~Foo () = default;
void set (const std::string & v)
{
value = v;
}
void set ()
{
lambda = [&]()
{
return this->value;
};
}
std::string get ()
{
return lambda();
}
std::string value;
std::function <std::string (void)> lambda;
};
int main ()
{
Foo foo;
foo.set ();
foo.set ("first");
std::cerr << foo.get () << std::endl; // prints "first"
foo.set ("captures change");
std::cerr << foo.get () << std::endl; // prints "captures change"
Foo foo2 (foo);
foo2.set ("second");
std::cerr << foo.get () << std::endl; // prints "captures change" (as desired)
std::cerr << foo2.get () << std::endl; // prints "captures change" (I would want "second" here)
return 0;
}
Thanks in advance.
The problem you're seeing is that the this pointer is being captured into the lambda, but you're now executing the copy of the function from another object. It's working in your example because both objects exist, but it's a dangling pointer waiting to happen.
The cleanest way to do this is to modify your std::function and your lambdas to take an argument of a pointer to the class, and use that passed in pointer instead of capturing this. Depending on the contents of your lambda, you can choose to capture the values.
class Foo
{
public:
Foo () = default;
~Foo () = default;
void set (const std::string & v)
{
value = v;
}
void set ()
{
lambda = [](Foo* self)
{
return self->value;
};
}
std::string get ()
{
return lambda(this);
}
std::string value;
std::function <std::string (Foo*)> lambda;
};
Example at IDEOne
I don't think you can modify the closure. If you need the function to operate on another object, you need to pass the pointer to the object as an argument to the function:
class Foo
{
public:
Foo () = default;
~Foo () = default;
void set (const std::string & v)
{
value = v;
}
void set ()
{
lambda = [](Foo* t)
{
return t->value;
};
}
std::string get ()
{
return lambda(this);
}
std::string value;
std::function <std::string (Foo*)> lambda;
};