I have my functor class that can encapsulate function/member function and arbitrary count of function parameters.
#include <tuple>
#include <stdlib.h>
#include <iostream>
template <class PARENT>
class FunctorHandlerBase
{
public:
typedef typename PARENT::TRET RTYPE;
typedef typename PARENT::TUP ARGS;
virtual RTYPE operator()(ARGS) { return RTYPE(0); };
};
template <class PARENT, typename MFUN>
class FunctorHandler : public FunctorHandlerBase<PARENT> {
public:
typedef typename PARENT::TRET RTYPE;
typedef typename PARENT::TUP ARGS;
FunctorHandler(MFUN pfun)
: pFun(pfun)
{}
virtual ~FunctorHandler() {};
virtual RTYPE operator()(ARGS args) {
return callPrivate(args, std::make_index_sequence<std::tuple_size_v<decltype(args)>>{});
}
private:
template<class Tuple, std::size_t... Is>
RTYPE callPrivate(Tuple&& tuple, std::index_sequence<Is...>)
{
return (*pFun)(std::get<Is>(std::forward<Tuple>(tuple))...);
}
MFUN pFun;
};
template <class PARENT, class POBJ, typename MFUN>
class MFunctorHandler : public FunctorHandlerBase<PARENT> {
public:
typedef typename PARENT::TRET RTYPE;
typedef typename PARENT::TUP ARGS;
MFunctorHandler(const POBJ &pobj, MFUN pfun)
: pObj(pobj), pFun(pfun)
{}
virtual ~MFunctorHandler() {};
virtual RTYPE operator()(ARGS args) {
return callPrivate(args, std::make_index_sequence<std::tuple_size_v<decltype(args)>>{});
}
private:
template<class Tuple, std::size_t... Is>
RTYPE callPrivate(Tuple&& tuple, std::index_sequence<Is...>)
{
return ((*pObj).*pFun)(std::get<Is>(std::forward<Tuple>(tuple))...);
}
POBJ pObj;
MFUN pFun;
};
template <typename RTYPE = void>
class FunctorBase
{
public:
virtual RTYPE operator()() {
return RTYPE(0);
}
};
template <typename RTYPE = void, class... Args>
class Functor : public FunctorBase<RTYPE>
{
public:
typedef RTYPE TRET;
typedef typename std::tuple<Args ...> TUP;
template<typename MFUN>
Functor(MFUN pfun, Args&&... args)
: mArgs(args...)
{
pImpl = QSharedPointer<FunctorHandlerBase<Functor>>(new FunctorHandler<Functor, MFUN>(pfun));
}
template<class POBJ, typename MFUN>
Functor(const POBJ &pobj, MFUN pfun, Args&&... args)
: mArgs(args...)
{
pImpl = QSharedPointer<FunctorHandlerBase<Functor>>(new MFunctorHandler<Functor, POBJ, MFUN>(pobj, pfun));
}
RTYPE operator()()
{
return (*pImpl)(mArgs);
}
std::tuple<Args ...> mArgs;
private:
QSharedPointer<FunctorHandlerBase<Functor>> pImpl;
};
template<typename RTYPE, class POBJ, typename MFUN, class... Args>
FunctorBase<RTYPE> *Create(const POBJ &pobj, MFUN pfun, Args&& ...args) {
return new Functor<RTYPE, Args...>(pobj, pfun, std::forward<Args...>(args)...);
}
class B
{
public:
B(){};
bool voidF() {
return true;
}
bool printInt(int x) {
std::cout << "print int:" << x;
return true;
}
};
int main(int argc, char *argv[])
{
B *b = new B;
auto *fb = Create<bool>(b, &B::printInt, 100);
std::cout << "function result" << (*fb)();
}
Can I deduce function return type from pointer to function in FunctorBase::Create()
function? To change "auto *fb = Create<bool>(b, &B::printInt, 100)
" to "auto *fb = Create(b, &B::printInt, 100)
".
Can I create Functor
base class without any template parameters? I want to pack some functions with different return types in vector and get function return type by std::is_same_v
. Now I can pack only functions with a same return type.
The example in the question is far from minimal, and is uncompilable anyway, but it seems that you're looking for std::invoke_result
:
template<class Pobj, typename Mfun, class... Args> // NOTE 1
auto *Create(const Pobj &pobj, Mfun pfun, Args&& ...args) {
return new Functor<std::invoke_result_t<Mfun, Pobj, Args...>, Args...>(pobj, pfun, std::forward<Args...>(args)...);
}
int main()
{
B *b = new B;
FunctorBase<bool> *fb = Create(b, &B::printInt, 100);
std::cout << "function result: " << (*fb)() << '\n';
delete fb; // NOTE 2
delete b;
}