Wrap a function pointer in C++ with variadic template

允我心安 提交于 2020-01-09 19:47:33

问题


The Question

I have a number of C++ functions void f(), R g(T a), S h(U a, V b) and so on. I want to write a template function that accepts f, g, h and so on as a template argument and calls that function.

ie I want something like this:

template<MagicStuff, WrappedFunction>
ReturnType wrapper(MagicallyCorrectParams... params)
{
    extra_processing(); // Extra stuff that the wrapper adds
    return WrappedFunction(params);
}
...
wrapper<f>(); // calls f
wrapper<g>(T()); // calls g
wrapper<h>(U(), V()); // calls h

Here's what I've tried so far:

Solution 1

template<typename ReturnType, typename Args...>
ReturnType wrapper(ReturnType (*wrappee)(Args...), Args... args)
{
    extra_processing();
    return wrappee(args...);
}
...
wrapper(f); // calls f OK
wrapper(g, T()); // calls g OK
wrapper(h, U(), V()); // calls h OK

This works but is unsatisfactory because in my case, I want the function pointer bound to the template instance. The function pointer is determinable statically at compile time and it is not desirable in my use case to have to pass it as a parameter at runtime.

Solution 2

template<
    typename ReturnType, typename Args...,
    ReturnType (*FuncPtr)(Args...)
>
wrapper(Args... args)
{
    extra_processing();
    return FuncPtr(args...);
}
...
wrapper<void, f>(); // calls f
wrapper<R, T, g>(T()); // calls g
wrapper<S, U, V, h>(U(), V()); // calls h

This works but is unsatisfactory because it is verbose. The return type and parameter types can be deduced from the function pointer itself. What would be perfect is a template specification so I can do wrapper<g>(T()) as indicated above.

Thanks for all help!


回答1:


template<typename Fn, Fn fn, typename... Args>
typename std::result_of<Fn(Args...)>::type
wrapper(Args&&... args) {
    return fn(std::forward<Args>(args)...);
}
#define WRAPPER(FUNC) wrapper<decltype(&FUNC), &FUNC>

//Usage:

int min(int a, int b){
    return (a<b)?a:b;
}

#include<iostream>
#include<cstdlib>
int main(){
    std::cout<<WRAPPER(min)(10, 20)<<'\n';
    std::cout<<WRAPPER(rand)()<<'\n';
}

Alternatively, to get maybe quite less readable, but shorter syntax:

#define WRAPPER(FUNC, ...) wrapper<decltype(&FUNC), &FUNC>(__VA_ARGS__)

//Usage:

int main(){
    sdt::cout<<WRAPPER(min, 10, 20)<<'\n';
    std::cout<<WRAPPER(rand)<<'\n';
}



回答2:


This is the best I've been able to do so far:

template<typename R, typename...A>
struct S<R(A...)>
{
    typedef R(*F)(A...);
    F f;
    constexpr S(F _f) : f(_f) { }
    inline R operator()(A... a)
    { return f(a...); }
};

#define wrapper(FUNC, ARGS...) (S<decltype(FUNC)>(FUNC))(ARGS)

int f(float g);

int main(void)
{
    return wrapper(f, 3.0f);
}

Sadly I can't make it compile under MSVC.




回答3:


There's a duplicate somewhere here, I remember it, but I can't find it... The conclusion of which being that it was impossible to pass the pointer's type and its value at the same time.

Some hope lies in a suggestion for implicit type template parameters, which you can find here.



来源:https://stackoverflow.com/questions/25392935/wrap-a-function-pointer-in-c-with-variadic-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!