I have two classes where one is logic and one is the model. After initializing both, I would like to bind a b.funB()
to a.funA()
where A a; B b;
.
class A{
public:
bool funA() { doStuff(); }
}
class B{
public:
bool funB();
Template<class T>
void bindBtoA((bool (B::*fun2)(), bool (T::*fun1)(), T *t){
funB=std::bind( ?);
// (fun1, t), (&T::fun1, &t), (T::fun1, t), ... ?
}
}
How do I bind these correctly and get rid of "can't convert" errors (I did use typedef in my actual code)
An answer using lambda is acceptable. But, funB
needs to be a callable as another engine needs to grab this (hint: Q_INVOKABLE), so using std::function
for A::funA
might not work for my case.
You can achieve this via the magic of std::function
, which would be hidden inside class B
and type-erases the function to be called, thereby giving you the generality you seek.
Here's a fully-worked example:
#include <iostream>
#include <functional>
class A
{
public:
bool funA () { std::cout << "funA\n"; return true; }
};
class B
{
public:
bool funB ()
{
return f ();
}
template <class T>
void bindBtoA (bool (T::*fun1) (), T *t)
{
f = [t, fun1] { return (t->*fun1) (); };
}
private:
std::function <bool ()> f;
};
int main()
{
A a;
B b;
b.bindBtoA <A> (&A::funA, &a);
std::cout << b.funB ();
}
I would think this would work with Q_INVOKABLE, but I don't actually know anything about it so you'd have to try it. But if it does work, it's a good way to do it.
Note: With the code as posted, you are responsible for keeping a
alive for as long as b
is alive. If you can't guarantee that, a better bet would be to use a std::shared_ptr
instead. Or copy a
inside bindBtoA
if that is a practical solution for you (which I'm guessing it isn't).