C++11 setting lambda in public function - c++

how to properly address this?
class House{
public:
void startAction();
void init(){
startAction = [] () {};
}
};
I have tried this, but it is said "Expression is not assignable"
I want to define the function of startAction, but inside the init method.
I do this because there's couple of variable in init method that i want to capture to pass to startAction.

You can't assign a value to a member function.
You could have a member variable that the member function calls, something like this:
class House{
public:
void startAction() { m_action(); }
void init(){
m_action = [] () {};
}
private:
std::function<void()> m_action;
};
But it's simpler to store the things you want to capture as members of House.

Try this:
class House {
public:
std::function<void ()> startAction;
void init() {
startAction = []() {};
}
};
int main() {
House house;
house.init();
house.startAction();
...
}

You can also instead of using std::function<void ()> use C style pointer to function. Look at the following code.
#include <iostream>
typedef void (*my_func)();
class House
{
public:
my_func m_ffunc;
void init()
{
m_ffunc = [](){ std::cout << "Hello from m_ffunc" << std::endl;};
}
};
int main()
{
House myHouse;
myHouse.init();
myHouse.m_ffunc();
return 0;
}

Related

Is it possible to replace member function to a noop function?

I write c++ with c++11 and have a question as title.
Ex.
class Hi {
public:
Hi(){};
test() {cout << "test" << endl;};
}
void noop(){
; // noop
};
int main(){
Hi hi();
hi.test = noop; // just example, not real case
return 0;
}
Is that possible to replace test() of class Hi to a noop function in runtime!? Thanks.
You can't replace any function at runtime, whether class member or not.
However, you can achieve the desired effect by using a variable.
(This is yet another example of the "add a level of indirection" method of solving problems.)
Example:
class Hi {
public:
Hi(): test([this]() { do_test(); }) {}
std::function<void()> test;
void do_test() { cout << "test" << endl; }
};
void noop(){}
int main(){
Hi hi;
hi.test(); // Outputs 'test'
hi.test = noop;
hi.test(); // Does nothing
}
You have to think object oriented. In this case you have to elevate your function to be an object we can name it MethodClass then your function in the class Hi will be a pointer to that class. Below a simple example
#include <memory>
class BaseMethodClass
{
public:
virtual void method() = 0;
};
class MethodClass1 : public BaseMethodClass
{
public:
virtual void method()
{
// your implementation here
}
};
class MethodClass2 : public BaseMethodClass
{
public:
virtual void method()
{
// your implementation here
}
};
class Hi
{
public:
Hi() { method = nullptr; };
void setMethod(BaseMethodClass* m) { method.reset(m); }
void test() { if (method) method->method(); };
private:
std::shared_ptr<BaseMethodClass> method;
};
int main()
{
Hi hi;
hi.setMethod(new MethodClass1());
hi.test();
hi.setMethod(new MethodClass2());
hi.test();
return 0;
}
This way you can override your methos as you want not just noop

What is the correct way to encapsulate helper functions in C++?

Given a class:
class myClass{
// ...
private:
int helperFuncForA();
int secondhelperFuncForA();
public:
void A();
// ...
};
Suppose that the helper functions are not used outside of A; how do I encapsulate them such that calling them outside of A is impossible? Do I do:
class myClass{
// ...
public:
class {
private:
int helperFuncForA();
int secondhelperFuncForA();
public:
void call();
} A;
// ...
};
and then call by writing:
myClass obj;
obj.A.call();
? Perhaps, I could overload A's () operator instead of making the call() function for convenience. What is the correct way?
The correct way is using of lambdas:
class myClass{
// ...
private:
// remove from here
//int helperFuncForA();
//int secondhelperFuncForA();
public:
void A();
// ...
};
// somewhere
void myClass::A()
{
auto helperFuncForA = [this]() -> int
{
//...
return 1;
};
auto secondhelperFuncForA = [this]() -> int
{
//...
return 2;
};
//...
int x = helperFuncForA();
x += secondhelperFuncForA();
}
If some method can only be used by in the function void A(), you probably need a class.
But you can do something like this if you want :
#include <iostream>
class ClassTest
{
public:
struct A{
private:
void helperFunc() {
std::cout << "Executing Helper Func " << std::endl;
}
public:
void operator() (){
helperFunc();
}
};
A a;
void classFunc(){
//a.helperFunc(); <- Impossible helperFunc private
a();
}
};
int main()
{
ClassTest c;
c.classFunc();// Print : Executing Helper Func
//OR
c.a();// Print e: Executing Helper Func
}

Using std::bind and std::function to use a class member function as callback for another class member routine

This may have been explored before, but I am not certain how it works out, and how t should in my particular case..
Essentially I have a class, with a callback defined as :
class Foo
{
public:
using someCallbackName = std::function<void(int)>;
void someFunc();
Foo(int, someCallBackName);
private :
someCallbackName m_callBack;
}
void Foo::someFunc()
{
m_callBack(1);
}
I used to call this in main() or by just referencing function of similar signature..
void someOtherFunction(int x)
{
cout << x;
}
int main()
{
Foo::someCallbackName callBack = someOtherFunction;
Foo foo(5, callBack);
}
I decided though, that I may need someOtherFunction as a class member, and put it as part of a class. However, using class member function someOtherFunction as a callback required making it static, which worked fine, but which would mean it wouldn't have access to non-static class members, which sort of defeated the purpose to put it in a class.
I tried using :
C++ callback using class member
and the struct access as given in :
https://en.cppreference.com/w/cpp/utility/functional/bind
..but it does not seem to work, the std::bind to
Foo::someCallbackName callBack = std::bind(not_sure_what_to_use_here);
keeps giving errors saying no suitable conversion, which makes me think that somewhere the signature of callback or mechanism of using std::bind in the code is erroneous.
Keeping class Foo as is, how can m_callBack call someOtherFunction ?
You can "bind" the callback to a non-static member function of a particular object by using labmda:
class X {
public:
void someOtherFunction(int x) const { std::cout << x; }
};
int main()
X x;
Foo::someCallbackName callBack = [&x](int i){ x.someOtherFunction(i); };
Foo foo(5, callBack);
foo.someFunc();
}
Live demo: https://wandbox.org/permlink/fUmrnD6xn1xr7zn0.
To avoid dangling references after x is destroyed, you can employ shared pointers, as follows (note it is captured by value):
Foo::someCallbackName callBack;
{
auto ptr_x = std::make_shared<X>();
callBack = [ptr_x](int i){ ptr_x->someOtherFunction(i); };
}
Foo foo(5, callBack);
foo.someFunc();
Live demo: https://wandbox.org/permlink/23euPcuDUsDENdRe.
As #Daniel Langr said, you can use a lambda function.
Otherwise if you want to use a callback that is a member function you need to bind it to an object.
#include <functional>
#include <iostream>
class Foo
{
public:
using someCallbackName = std::function<void(int)>;
void someFunc();
Foo(int, someCallbackName);
private:
someCallbackName m_callBack;
};
class Bar
{
public:
void someOtherFunction(int x);
};
Foo::Foo(int i, someCallbackName cb)
{
m_callBack = cb;
someFunc();
}
void Foo::someFunc()
{
m_callBack(1);
}
void Bar::someOtherFunction(int x)
{
std::cout << x;
}
int main()
{
Bar bar;
Foo::someCallbackName callBack = std::bind(&Bar::someOtherFunction, &bar, std::placeholders::_1);
Foo foo(5, callBack);
}
Be careful about the lifetime of barwhen doing this.
Oone way to adress the lifetime issue is to make Foo responsible for the lifetime of Bar (this design pattern is called a composition).
#include <functional>
#include <iostream>
// If you declare both class in different files you may need to look into "forward declaration"
class Bar
{
public:
void someOtherFunction(int x);
};
class Foo
{
public:
using someCallbackName = std::function<void(int)>;
void someFunc();
Foo(int, someCallbackName);
private:
someCallbackName m_callBack;
Bar bar;
};
Foo::Foo(int i)
{
m_callBack = std::bind(&Bar::someOtherFunction, &bar, std::placeholders::_1);;
someFunc();
}
// someOtherFunction and someFunc are left unchanged
int main()
{
Foo foo(5);
}

C++ assign member object function to class member function

Is there a way to use an = type assignment instead of this syntax:
void triggerAttack() { adsr.triggerAttack(); }
I was hoping to do something like:
void triggerAttack() = adsr.triggerAttack
std::function<void()> triggerAttack = adsr.triggerAttack
void(*triggerAttack)() = adsr.triggerAttack
but nothing compiles!
example code:
class LinearADSR
{
public:
void triggerAttack() { }
};
class JerobeamBlubb : public gen
{
public:
void triggerAttack() { adsr.triggerAttack(); }
protected:
LinearADSR adsr;
};
In general, a member function pointer differs from usual pointers, since it has to be used with an instance of its class.
So change your code to this:
class LinearADSR
{
public:
void triggerAttack() { }
};
class JerobeamBlubb
{
public:
void (LinearADSR::*triggerAttack)();
protected:
LinearADSR adsr;
};
int main()
{
JerobeamBlubb a;
a.triggerAttack = &LinearADSR::triggerAttack;
}
About your failed attempts:
void triggerAttack() = adsr.triggerAttack; is invalid syntax
std::function<void()> triggerAttack = adsr.triggerAttack fails because triggerAttack is a member function, and not a usual function. You need an instance of its class as I explained before.
void(*triggerAttack)() = adsr.triggerAttack fails for the same reason as above.

Pass method as callback from one class to other class

I have 2 class, I would like to pass a method from one to other by callback!
See that I also wish to hold the address of this method using void (*callBack)();
I'm used to do this in C, but I dont know how to do this in c++;
#include <iostream>
using namespace std;
class A
{
private:
void (*callBack)(); //to hold the address of the method
public:
A();
void setCallBack(void(*cB)());
void useCallBack();
};
A::A()
{
}
void A::setCallBack(void(*cB)())
{
callBack = cB;
}
void A::useCallBack()
{
callBack();
}
class B
{
private:
A * Aguy;
public:
B();
void someMethod();
void otherMethod();
};
B::B()
{
Aguy = new A();
}
void B::otherMethod()
{
Aguy->setCallBack(someMethod);
Aguy->useCallBack()
}
void B::someMethod()
{
cout << "Hello. I'm from class b" << endl;
}
int main()
{
B Bguy;
Bguy.otherMethod();
return 0;
}
The problem is that:
void (*callBack)();
This is not a pointer to a method. This is a pointer to a function.
To have a pointer to a method you need to specify the class the method is in.
void (B::*callBack)();
Then when you call it you need to call it via an object.
void A::useCallBack(B* b)
{
(b->*callBack)();
}
But this is probably not what you want.
What you really want is a wrapper that encapsulates all this.
I would take a look at std::function. This will allow you to wrap a method call and an object into a single object that you can then call.
std::function<void()> callback;
Just replace all your occurrences of void(*cB)() with std::function<void()> then you can bind an instance of the object to the method at the call point.
Aguy->setCallBack(std::bind(&B::someMethod, this));
This also allows you to seemly pass any normal function or functor as a callback.
void print()
{ std:cout << "It worked\n";
}
...
Aguy->setCallBack(&print);
struct Printer
{
void operator()() const
{
std::cout << "It worked with obejct\n";
}
}
...
Aguy->setCallBack(Printer());
If you need to pass member function pointers see the modified code. it uses modern c++ constructs.
#include <iostream>
#include <functional>
using namespace std;
class A
{
private:
typedef std::function<void()> some_void_function_type;
some_void_function_type f_;
public:
A();
void setCallBack(some_void_function_type f);
void useCallBack();
};
A::A()
{
}
void A::setCallBack(some_void_function_type f)
{
f_ = f;
}
void A::useCallBack()
{
f_();
}
class B
{
private:
A * Aguy;
public:
B();
void someMethod();
void otherMethod();
};
B::B()
{
Aguy = new A();
}
void B::otherMethod()
{
Aguy->setCallBack(std::bind(&B::someMethod, this));
Aguy->useCallBack();
}
void B::someMethod()
{
cout << "Hello. I'm from class b" << endl;
}
int main()
{
B Bguy;
Bguy.otherMethod();
return 0;
}
See c++ - <unresolved overloaded function type> for details.
To quote the answer:
In C++, member functions have an implicit parameter which points to
the object (the this pointer inside the member function). Normal C
functions can be thought of as having a different calling convention
from member functions, so the types of their pointers
(pointer-to-member-function vs pointer-to-function) are different and
incompatible. C++ introduces a new type of pointer, called a
pointer-to-member, which can be invoked only by providing an object.
Put static on someMethod:
class B
{
private:
A * Aguy;
public:
B();
static void someMethod();
void otherMethod();
};
void B::otherMethod() {
Aguy->setCallBack(B::someMethod);
Aguy->useCallBack(); // adding missing semicolon
}