I am currently trying to implement a member function of a class which allows for setting a callback that is either itself a member function (of a potentially different class) or a pure function not being part of a class.
Given such a class,
#include <boost/signals2.hpp> // for callback
class CallbackSetter
{
template <typename T>
void setCallback(T &p_rCallback)
{
m_oCallback.connect(boost::bind(&p_rCallback, _1);
}
boost::signals2::signal<void(const std::string &p_rTLName)> m_oCallback;
}
CallbackSetter oSetter;
oSetter.setCallback(theFunction);
works fine for non-member methods. However I am sort of failing implementing something that lets the user connect to either a member of not. This is what I tried:
class CallbackSetter
{
template <typename T, typename Cl,
typename std::enable_if_t<!std::is_class<Cl>::value>>
void setCallback(T &p_rCallback, Cl & p_rCallbackclass)
{
m_oCallback.connect(boost::bind(&p_rCallback, p_rCallbackclass, _1);
}
template <typename T, typename Cl,
typename std::enable_if_t<std::is_class<Cl>::value> >
void setSignalChangeCallback(T &p_rCallback, Cl & p_rCaller)
{
m_oObserverCallback.connect(boost::bind(&p_rCallback, p_rCaller, _1));
}
}
called by some other classes' member function like this:
#include <string>
class OtherClass
{
void caller()
{
m_oMyCS.setCallback(&OtherClass::executeMe, this);
}
void executeMe(std::string &p_rTag)
{
// do whatever with p_rTag
}
CallbackSetter m_oMyCS;
}
and finally
void noMemberExec(std::string &p_rTag)
{
// do whatever
}
int main()
{
OtherClass oOC;
oOC.caller();
CallbackSetter oCS;
oCS.setCallback(&noMemberExec, nullptr);
return 0;
}
Any help here is welcome!
P.S.: I am using VS 2015, which quits with an error
C2783: error calling 'setCallback(T&, CL&)': could not deduce template argunemt for '__formal'
Instead of having different overloads for setCallback()
and trying to account for different situations - just provide one:
template <class F>
void setCallback(F f)
{
m_oCallback.connect(f);
}
It's just up to the user to provide a function that can be called with a std::string const&
. If I want it to call a free function taking a single argument, I just do that:
oCS.setCallback(noMemberExec);
if I want it to call a member function on a class instance, I do it explicitly:
m_oMyCS.setCallback([this](std::string const& arg){ executeMe(arg); });
Either way, I'm passing a single-argument callable into setCallback()
.