允许可变参数计数的函数作为模板函数参数
Allow function of variadic argument count as template function argument
在 C++ 中,我们可以很容易地定义模板函数参数,如 this 问题中所示。但是,这只允许具有已定义参数列表和 return 值的函数。
我们可以像这样制作这些类型的模板参数:
template<typename R, typename P, R(*Func)(P)>
R proxy_func(P arg)
{
// do some stuff...
R&& res{ Func(std::forward(arg)) };
// do some more stuff...
return res;
}
但是,这里我们仍然限制在固定数量的参数。
像下面这样的尝试不会编译(至少在 MSVC 19.24.28315 上),因为 " 模板参数 'Func' 不能使用,因为它遵循模板参数包并且不能从'proxy_func'".
的函数参数推导出来
template<typename R, typename... P, R(*Func)(P...)>
R proxy_func(P... args)
{
// do some stuff...
R&& res{ Func(std::forward(args)...) };
// do some more stuff...
return res;
}
那么允许任意函数作为模板参数的选项是什么 - 同样重要的是 - 允许其 参数 用作函数模板的参数它用于(如上面的 proxy_func
)?理想情况下,我将能够使用任何函数调用 proxy_func
作为(理想情况下 单个 )模板参数 Func
并能够应用其(proxy_func
's) Func
.
的参数
编辑: 我特别感兴趣的是有一个函数-实例作为模板参数(例如允许模板实例化proxy_func
以根据个人 Func
s).
应用编译时优化
从某种意义上说,您link的问答是复杂的方式。简单的方法是:
template <typename F>
void foo(F f) {
f(); // call the function
}
在您的情况下,可以推导出 return 值,并且可以从 foo
的参数推导出参数类型。请注意,它们不必完全匹配 f
的参数类型,只要可以用它们调用 f
即可:
template <typename F,typename ... Args>
auto foo( F f, Args ... args) {
return f(args...); // call the function
}
为了简洁起见,我暂时省略了转发和存储调用结果,但答案仍然适用。
如果你想要函数本身,而不是它的类型作为模板参数(抱歉我先错过了那部分)这仍然有效:
template <auto f,typename ... Args>
auto foo(Args ... args) {
return f(args...); // call the function
}
但是,如果 f
是 lambda,这将不起作用。详情请看这里:https://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter
感谢 C++17,auto
可以用作 non-type 模板参数的占位符,然后我们可以在没有类型声明的情况下传递函数指针:
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();
}
在 C++ 中,我们可以很容易地定义模板函数参数,如 this 问题中所示。但是,这只允许具有已定义参数列表和 return 值的函数。
我们可以像这样制作这些类型的模板参数:
template<typename R, typename P, R(*Func)(P)>
R proxy_func(P arg)
{
// do some stuff...
R&& res{ Func(std::forward(arg)) };
// do some more stuff...
return res;
}
但是,这里我们仍然限制在固定数量的参数。
像下面这样的尝试不会编译(至少在 MSVC 19.24.28315 上),因为 " 模板参数 'Func' 不能使用,因为它遵循模板参数包并且不能从'proxy_func'".
的函数参数推导出来template<typename R, typename... P, R(*Func)(P...)>
R proxy_func(P... args)
{
// do some stuff...
R&& res{ Func(std::forward(args)...) };
// do some more stuff...
return res;
}
那么允许任意函数作为模板参数的选项是什么 - 同样重要的是 - 允许其 参数 用作函数模板的参数它用于(如上面的 proxy_func
)?理想情况下,我将能够使用任何函数调用 proxy_func
作为(理想情况下 单个 )模板参数 Func
并能够应用其(proxy_func
's) Func
.
编辑: 我特别感兴趣的是有一个函数-实例作为模板参数(例如允许模板实例化proxy_func
以根据个人 Func
s).
从某种意义上说,您link的问答是复杂的方式。简单的方法是:
template <typename F>
void foo(F f) {
f(); // call the function
}
在您的情况下,可以推导出 return 值,并且可以从 foo
的参数推导出参数类型。请注意,它们不必完全匹配 f
的参数类型,只要可以用它们调用 f
即可:
template <typename F,typename ... Args>
auto foo( F f, Args ... args) {
return f(args...); // call the function
}
为了简洁起见,我暂时省略了转发和存储调用结果,但答案仍然适用。
如果你想要函数本身,而不是它的类型作为模板参数(抱歉我先错过了那部分)这仍然有效:
template <auto f,typename ... Args>
auto foo(Args ... args) {
return f(args...); // call the function
}
但是,如果 f
是 lambda,这将不起作用。详情请看这里:https://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter
感谢 C++17,auto
可以用作 non-type 模板参数的占位符,然后我们可以在没有类型声明的情况下传递函数指针:
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();
}