1

Is there some way to have the compiler infer template arguments from a method's signature?

I have this class, based off of the article The Impossibly Fast C++ Delegates.

template<typename... Ds>
class Delegate {
public:
    Delegate()
        : object_ptr(0)
        , stub_ptr(0)
    {}

    template <class T, void (T::*TMethod)(Ds...)>
    static Delegate from_member(T* object_ptr)
    {
        Delegate d;
        d.object_ptr = object_ptr;
        d.stub_ptr = &method_stub<T, TMethod>; // #1
        return d;
    }

    void operator()(Ds... ds) const
    {
        return (*stub_ptr)(object_ptr, ds...);
    }

private:
    typedef void (*stub_type)(void* object_ptr, Ds...);

    void* object_ptr;
    stub_type stub_ptr;

    template <class T, void (T::*TMethod)(Ds...)>
    static void method_stub(void* object_ptr, Ds... ds)
    {
        T* p = static_cast<T*>(object_ptr);
        return (p->*TMethod)(ds...); // #2
    }
};

To instantiate this class, one would say

struct Foo {
    void foo(int x, double y) {
        std::cout << "foo(" << x << ", " << y << ")" << std::endl;
    }
};

int main() {
    Foo f;
    auto d = Delegate<int, double>::from_member<Foo, &Foo::foo>(&f);
    d(1, 2.3);
}

My question is this: Is there some way to get the compiler to infer the method parameter types from the method itself? That is, can I avoid having to specify <int, double> when creating a delegate, and have the compiler figure this out for me? I would like to be able to say something along the lines of DelegateFactory::from_member<Foo, &Foo::foo>(&f).

mindvirus
  • 5,016
  • 4
  • 29
  • 46
  • 1
    Why don't you simply use C++11 lambas or `std::function`? The article you've read is 9 years old, i.e. an eternity. – Walter Aug 22 '14 at 19:42
  • @Walter The short answer is just academic interest - I was playing with the idea, and couldn't figure out how to accomplish this. The article is still relevant though - see some discussion here: http://stackoverflow.com/q/11126238/31455 – mindvirus Aug 22 '14 at 19:55
  • 1
    You would likely want to overload this to work with `const` member functions also, i.e. `template`. And if you really want to be thorough, `volatile` and `const volatile`, not like anyone ever uses those. – aschepler Aug 22 '14 at 20:41
  • I'm not convinced that this is a duplicate of the linked question - I'm not asking here how to determine the parameters of a function, but rather make them implicit. – mindvirus Aug 24 '14 at 21:19

1 Answers1

3
#include <iostream>

template <typename... T>
class Delegate
{
};

template <typename T, typename... Args>
Delegate<Args...> from_member(T* t, void (T::*)(Args...))
{
    return Delegate<Args...>(/* fill in, you have all data you need */);
}

struct Foo
{
    void foo(int x, double y)
    {
        std::cout << "foo(" << x << ", " << y << ")" << std::endl;
    }
};

int main()
{
    Foo f;
    auto d = from_member(&f, &Foo::foo);

    return 0;
}
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160