Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
252 views
in Technique[技术] by (71.8m points)

c++ - Is it possible to extract parameter types from a template <auto MEMFN>?

Is it possible to create a standalone template function which has a template parameter auto MEMFN (a member function pointer), and has the same return and parameter types as MEMFN has?

So, if MEMFN's type is

RETURN (OBJECT::*)(PARAMETERS...)

then the desired function is this:

template <auto MEMFN>
RETURN foo(OBJECT &, PARAMETERS...);

My problem is how to extract PARAMETERS... from MEMFN's type (RETURN and OBJECT are easy to do).

So I can call this function like this:

Object o;
foo<&Object::func>(o, <parameters>...);

As for request from n.m., here is a stripped down example from an actual code:

#include <utility>

template <typename RETURN, typename OBJECT, typename ...PARAMETERS>
struct Wrapper {
    template <RETURN (OBJECT::*MEMFN)(PARAMETERS...)>
    RETURN foo(PARAMETERS... parameters) {
        // do whatever with MEMFN, parameters, etc. here, not part of the problem
    }
};

struct Object {
    template <auto MEMFN, typename RETURN, typename OBJECT, typename ...PARAMETERS>
    RETURN call(OBJECT &&object, PARAMETERS &&...parameters) {
        // here, MEMFN parameters and PARAMETERS must be the same

        // Wrapper actually not created here, it is accessed by other means
        Wrapper<RETURN, typename std::decay<OBJECT>::type, PARAMETERS...> w;

        return w.template foo<MEMFN>(std::forward<PARAMETERS>(parameters)...);
    }
};

struct Foo {
    void fn(int);
};

int main() {
    Object o;
    Foo f;
    o.call<&Foo::fn, void, Foo &, int>(f, 42);

    // this is wanted instead:
    // o.call<&Foo::fn>(f, 42);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes we can:

template <auto MemFn>
struct fooHelper;

template <typename Ret, typename Obj, typename ... Args, Ret (Obj::*MemFn)(Args...)>
struct fooHelper<MemFn>
{
    static Ret call(Obj& obj, Args... args) {
        return (obj.*MemFn)(args...);
    }
};

template <auto MemFn, typename ... Args>
auto foo(Args ... args)
{
    return fooHelper<MemFn>::call(args...);
}

Another way to define foo which doesn't introduce a brand new parameter pack is:

template <auto MemFn>
auto& foo = fooHelper<MemFn>::call;

Example usage:

#include <iostream>

struct moo
{
    int doit (int x, int y) { return x + y; }
};

int main()
{
    moo m;
    std::cout << foo<&moo::doit>(m, 1, 2) << "
";
}

(Perfect forwarding omitted for simplicity)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...