Search code examples
c++delegates

I'm trying to implement a delegate in c++, but I don't understand how to actually pass the delegate into a function


I'm trying to just use the code from this article: http://blog.coldflake.com/posts/C++-delegates-on-steroids/

So the delegate is this:

class Delegate
{
    typedef void (*Type)(void* callee, int);
public:
    Delegate(void* callee, Type function)
        : fpCallee(callee)
        , fpCallbackFunction(function) {}
    template <class T, void (T::*TMethod)(int)>
    static Delegate from_function(T* callee)
    {
        Delegate d(callee, &methodCaller<T, TMethod>);
        return d;
    }
    void operator()(int x) const
    {
        return (*fpCallbackFunction)(fpCallee, x);
    }
private:
    void* fpCallee;
    Type fpCallbackFunction;
    template <class T, void (T::*TMethod)(int)>
    static void methodCaller(void* callee, int x)
    {
        T* p = static_cast<T*>(callee);
        return (p->*TMethod)(x);
    }
};

And a class with the function I want to use is this:

class A
{
public:
    void foo(int x)
    {
        printf("foo called with x=%d\n", x);
    }
    void bar(int x) {}
};

And he shows how to use it here:

int main()
{
    A a;
    Delegate d = Delegate::from_function<A, &A::foo>(&a);
    d(42);
}

This works nicely, but the idea is to be able to actually pass this delegate into a function without any dependencies.

So if I have a new function that takes a string and prints it...

void printString(const std::string& str) {
    std::cout << str << std::endl;
}

How do I modify the parameters passed into this printString function so that it can take this delegate? What is the parameter type for the new delegate "d" that I made?

Something like...

void printString(const std::string& str, auto d) {
        std::cout << str << std::endl;
        // and then I can do something with d here
    }

So that I can then make main() this:

int main()
    {
        A a;
        Delegate d = Delegate::from_function<A, &A::foo>(&a);
        d(42);
        printString("foo", d(42));    <- note I don't know if I include the (42) here
    }

So the question is, what do I put as the parameters in printString so that I can pass d into it?


Solution

  • You can't easily pass the Delegate with an included parameter to another function.

    Note that with c++11 lambdas or std::bind/std::function the Delegate class isn't necessary:

    int main()
        {
            A a;
            printString("foo", std::bind(&A::foo, a, 42));
            printString("foo", std::bind_front(&A::foo, a, 42));
            printString("foo", [&]{ a.foo(42); });
        }
    

    If you do still want to use the Delegate class then these techniques still apply:

    int main()
        {
            A a;
            Delegate d = Delegate::from_function<A, &A::foo>(&a);
            auto delegateOp = &Delegate::operator();
            printString("foo", std::bind(delegateOp, d, 42));
            printString("foo", std::bind_front(delegateOp, d, 42));
            printString("foo", [&]{ d(42); });
        }
    

    https://godbolt.org/z/rzohE4Knj