使用可变参数模板将函数指针包装在C++中

Wrap a function pointer in C++ with variadic template

本文关键字:指针 函数 包装 C++ 变参 参数      更新时间:2023-10-16

问题

我有许多C++函数void f()R g(T a)S h(U a, V b)等。我想编写一个模板函数,它接受fgh等作为模板参数并调用该函数。

我想要这样的东西:

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

这是我到目前为止尝试过的:

解决方案 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

这有效但不令人满意,因为就我而言,我希望函数指针绑定到模板实例。函数指针在编译时是静态可确定的,在我的用例中,在运行时必须将其作为参数传递是不可取的。

解决方案 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

这有效,但不能令人满意,因为它很冗长。返回类型和参数类型可以从函数指针本身推导出来。完美的是模板规范,因此我可以如上所述wrapper<g>(T())

感谢大家的帮助!

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>

//用法:

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';
}

或者,要获得可读性可能较差但更短的语法:

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

//用法:

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

这是我迄今为止能够做的最好的:

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);
}

可悲的是,我无法在 MSVC 下编译它。

这里有一个副本,我记得它,但我找不到它......其结论是不可能同时传递指针的类型及其值。

一些希望在于对隐式类型模板参数的建议,您可以在此处找到。