October 22, 2024
Chicago 12, Melborne City, USA
templates

How do I deduce one template parameter from another?


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)();
}
  1. 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)".

  2. 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.



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video