感谢 C++17,auto 可以作为非类型模板参数的占位符,然后我们可以在没有类型声明的情况下传递函数指针:
template<auto func, typename... Args>
auto proxy_func(Args&&... args){
// do something...
auto result = func(std::forward<Args>(args)...);
// do something...
return result;
}
而且在 C++17 之前非常累人。如果你真的想要,你必须使用包装器:
int foo(){ return 0; };
template<typename Ret, typename... Args>
struct func_wrapper{
template<Ret(*func)(Args...)>
struct helper{
typedef Ret return_type;
typedef std::tuple<Args...> parameter_types;
static constexpr Ret (*value)(Args...) = func;
};
};
template<typename Ret, typename... Args>
auto helper(Ret(*)(Args...))->func_wrapper<Ret, Args...>;
template<typename Wrapper, typename... Args>
auto proxy_func(Args&&... args)
->decltype(Wrapper::value(std::forward<Args>(args)...)){
// do something...
auto result = Wrapper::value(std::forward<Args>(args)...);
// do something...
return result;
}
int main(){
typedef decltype(helper(&foo)) wrapper_klass;
typedef wrapper_klass::helper<&foo> wrapper_type;
proxy_func<wrapper_type>();
}
然后,如果您想通过func 决定Args,您必须使用一些棘手的方法来解压缩参数包:
template<auto>
struct proxy_func_klass;
template<typename Ret, typename... Args, Ret(*func)(Args...)>
struct proxy_func_klass<func>{
static Ret call(Args... args){
return func(args...);
}
};
和 C++11 版本:
int foo(){ return 0; };
template<typename Ret, typename... Args>
struct func_wrapper{
template<Ret(*func)(Args...)>
struct helper{
typedef Ret return_type;
typedef std::tuple<Args...> parameter_types;
static constexpr Ret (*value)(Args...) = func;
};
};
template<typename Ret, typename... Args>
auto helper(Ret(*)(Args...))->func_wrapper<Ret, Args...>;
template<typename, typename, typename>
struct helper_klass;
template<typename Self, typename Ret, typename... Args>
struct helper_klass<Self, Ret, std::tuple<Args...>>{
static Ret call(Args... args){
return Self::value(args...);
}
};
template<typename Wrapper>
struct proxy_func_klass : public helper_klass<proxy_func_klass<Wrapper>, typename Wrapper::return_type, typename Wrapper::parameter_types>{
static constexpr auto value = Wrapper::value;
};
int main(){
typedef decltype(helper(&foo)) wrapper_klass;
typedef wrapper_klass::helper<&foo> wrapper_type;
proxy_func_klass<wrapper_type>::call();
}