使用可变参数模板在C ++中包装函数指针 [英] Wrap a function pointer in C++ with variadic template

查看:141
本文介绍了使用可变参数模板在C ++中包装函数指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题



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



 模板< MagicStuff,WrappedFunction> 
ReturnType wrapper(MagicallyCorrectParams ... params)
{
extra_processing(); //额外的东西包装器添加
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()); //调用h OK

这是可行的,但是不能令人满意,因为在我的case,到模板实例。函数指针在编译时可以静态确定,在我的用例中不希望在运行时将其作为参数传递。



解决方案2



 模板< 
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()); // call g
wrapper< S,U,V,h>(U(),V()); // calls h

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


解决方案

 模板< 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)<'\\\
'
std :: cout<< WRAPPER(rand)()<<'\\\
';
}

或者,要获得更少的可读性, >

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

//用法:

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


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!

解决方案

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

这篇关于使用可变参数模板在C ++中包装函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆