如何包装 std::function 并轻松访问其 return 和参数类型?
How can I wrap a std::function and have easy access to its return and argument types?
我正在尝试做一些可以简化为以下内容的事情:
#include <functional>
#include <initializer_list>
#include <vector>
template <typename Ret, typename... Args>
struct func_wrapper
{
public:
using Func = std::function<Ret(Args...)>;
Ret operator()(Args && ...args)
{
return _impl(std::forward<Args>(args)...);
}
void another_function(int another_arg, Args && ...args) { }
/// and so on
private:
Func _impl;
};
func_wrapper<void(int, float)> f;
基本上,我想创建一个包装 std::function
的类型并为我的应用程序添加一些其他功能。在我的类型中,我希望能够在 class 接口中自由使用 return 类型 Ret
和自变量参数包 Args
。但是,when I try to compile the above with gcc 8.3, I get an error:
<source>: In instantiation of 'struct func_wrapper<void(int, float)>':
<source>:20:32: required from here
<source>:9:45: error: function returning a function
using Func = std::function<Ret(Args...)>;
^
<source>:11:9: error: function returning a function
Ret operator()(Args && ...args)
我不确定该错误是怎么回事。有没有一种简单的方法可以做我想做的事?
问题是你必须使用偏特化
template <typename>
struct func_wrapper;
template <typename Ret, typename... Args>
struct func_wrapper<Ret(Args...)>
{
// ...
};
如果你写
template <typename Ret, typename... Args>
struct func_wrapper
{
// ...
};
声明 f
为
func_wrapper<void(int, float)> f;
您将 Ret
推导为 void(int, float)
,将 Args...
可变参数列表推导为空列表。
所以,当你定义
using Func = std::function<Ret(Args...)>;
Func
声明变为
// ............................V..........VVV function-function type ?
using Func = std::function<void(int, float)()>;
给出 "error: function returning a function" 错误。
您必须将 func_wrapper
声明为接收单个类型名称
template <typename>
struct func_wrapper;
所以你可以传递函数的类型(void(int, float)
在你的例子中)作为模板参数,然后是模板特化
template <typename Ret, typename... Args>
struct func_wrapper<Ret(Args...)>
{
// ...
};
可以从函数类型解析 return 类型和参数类型。
@max66 的回答很好地展示了如何避免您 运行 遇到的问题。有关此处具体不起作用的更多信息,请查看您如何参数化模板以及如何使用它:
template <typename Ret, typename... Args> struct func_wrapper {
...
};
这意味着您的模板希望您通过编写类似
的内容来实例化它
func_wrapper<int, float> // Function taking a float and returning an int
func_wrapper<void, int, float> // Function taking a float and an int and returning void
func_wrapper<int> // Function taking no arguments and returning void
请特别注意,func_wrapper<T>
意味着 Ret
将是 T
并且该函数将不带任何参数。
因此,当你写
func_wrapper<void(int, float)>
你说的 "a function representing something that takes no arguments and returns a function that takes in an int
and a float
and returns void
," 这不是你想要的。这就是为什么您会收到有关返回非法函数的错误。
我正在尝试做一些可以简化为以下内容的事情:
#include <functional>
#include <initializer_list>
#include <vector>
template <typename Ret, typename... Args>
struct func_wrapper
{
public:
using Func = std::function<Ret(Args...)>;
Ret operator()(Args && ...args)
{
return _impl(std::forward<Args>(args)...);
}
void another_function(int another_arg, Args && ...args) { }
/// and so on
private:
Func _impl;
};
func_wrapper<void(int, float)> f;
基本上,我想创建一个包装 std::function
的类型并为我的应用程序添加一些其他功能。在我的类型中,我希望能够在 class 接口中自由使用 return 类型 Ret
和自变量参数包 Args
。但是,when I try to compile the above with gcc 8.3, I get an error:
<source>: In instantiation of 'struct func_wrapper<void(int, float)>':
<source>:20:32: required from here
<source>:9:45: error: function returning a function
using Func = std::function<Ret(Args...)>;
^
<source>:11:9: error: function returning a function
Ret operator()(Args && ...args)
我不确定该错误是怎么回事。有没有一种简单的方法可以做我想做的事?
问题是你必须使用偏特化
template <typename>
struct func_wrapper;
template <typename Ret, typename... Args>
struct func_wrapper<Ret(Args...)>
{
// ...
};
如果你写
template <typename Ret, typename... Args>
struct func_wrapper
{
// ...
};
声明 f
为
func_wrapper<void(int, float)> f;
您将 Ret
推导为 void(int, float)
,将 Args...
可变参数列表推导为空列表。
所以,当你定义
using Func = std::function<Ret(Args...)>;
Func
声明变为
// ............................V..........VVV function-function type ?
using Func = std::function<void(int, float)()>;
给出 "error: function returning a function" 错误。
您必须将 func_wrapper
声明为接收单个类型名称
template <typename>
struct func_wrapper;
所以你可以传递函数的类型(void(int, float)
在你的例子中)作为模板参数,然后是模板特化
template <typename Ret, typename... Args>
struct func_wrapper<Ret(Args...)>
{
// ...
};
可以从函数类型解析 return 类型和参数类型。
@max66 的回答很好地展示了如何避免您 运行 遇到的问题。有关此处具体不起作用的更多信息,请查看您如何参数化模板以及如何使用它:
template <typename Ret, typename... Args> struct func_wrapper {
...
};
这意味着您的模板希望您通过编写类似
的内容来实例化它func_wrapper<int, float> // Function taking a float and returning an int
func_wrapper<void, int, float> // Function taking a float and an int and returning void
func_wrapper<int> // Function taking no arguments and returning void
请特别注意,func_wrapper<T>
意味着 Ret
将是 T
并且该函数将不带任何参数。
因此,当你写
func_wrapper<void(int, float)>
你说的 "a function representing something that takes no arguments and returns a function that takes in an int
and a float
and returns void
," 这不是你想要的。这就是为什么您会收到有关返回非法函数的错误。