Search code examples
c++c++11embeddedfunctor

C++ Functor template for class member functions


There is a small functor class I wrote which should be able to call class member functions by hiding a static wrapper function and a void pointer to the object. The example below does not compile due to an error when setting the wrapper function. What I want is a class member pointer as template argument. Does anyone know what is wrong there?

I think there could be another problem in the static function when calling the member function. I do not exactly know how to do this with template syntax. The minimal example compiles with C++11 enabled gcc.

#include <iostream>

template<class TReturn, class... TParameter>
struct Functor {

    TReturn (*ptr)(void*, TParameter...);
    void     *object;

    template<class TObject, class TMemberFunction>
    static TReturn memberCaller(void *obj, TParameter... params) {
        TObject *c = static_cast<TObject*>(obj);
        return (c->*(TObject::TMemberFunction))(params...);
    }

    TReturn operator()(TParameter... params) {
        return ptr(object, params...);
    }
};

class Test {
public:
    void func(int a) {
        std::cout << a << std::endl;
    }
};

int main(int argc, const char **argv) {
    Functor<void, int> f;
    Test               t;

    f.object = &t;
    f.ptr    = &Functor<void, int>::memberCaller<Test, Test::func>;

    f(100);
}

Solution

  • Will something like this work for you?

    #include <iostream>
    
    template<class TObject, class T, class... TParameter>
    struct Functor {
    
        using TMemberFunction = T (TObject::*)(TParameter...);
        TMemberFunction ptr;
        TObject     *object;
    
    
        T operator()(TParameter... params) {
            return (object->*ptr)(params...);
        }
    };
    
    class Test {
    public:
        void func(int a) {
            std::cout << a << std::endl;
        }
    };
    
    template<typename T>
    class TD;
    
    int main() 
    {
        Functor<Test, void , int> f;
        Test               t;
    
        f.object = &t;
        f.ptr = &Test::func;
    
        f(100);
    }