使用 std::function 作为具有任意数量参数的数据成员

Using std::function as data member with arbitrary number of arguments

本文关键字:任意数 参数 数据成员 std function 使用      更新时间:2023-10-16

>我正在尝试创建一个具有std::function作为数据成员的类。

像这样:

template<typename ... Args>
using Function = std::function<void(Args...)>;
struct UI_Element
{
std::shared_ptr<UI_Element> parent;
std::vector<std::shared_ptr<UI_Element>> children;
Function<> callbackFunc;
template<typename F>
void registerCallbackFunc(const F& f)
{
callbackFunc = f;
}
template<typename ... Args>
void doFunc(Args&& ... args)
{
callbackFunc(std::forward<Args>(args)...);
}
};

问题是它显然适用于不接受任何参数的函数(由于 Function<>(。例如

void doStuff() 
{
std::cout << "This function worksn";
}

有没有办法注册包含任意数量参数的回调函数?

还是其他方式,不使用std::function来实现我想要的?

每个具有不同参数列表的std::function都是一个单独的类。由于成员只能具有一种类型,因此实现此目的的唯一方法是隐藏该类型。

因此,这在技术上可以通过将函数包装器存储在std::any中来实现。也许可以编写一个更具体的"任何函数"包装器,但遵循"工作":

std::any callbackFunc;
template<typename ... Args>
void registerCallbackFunc(std::function<void(Args...)> f)
{
callbackFunc = std::function(f);
}
template<typename ... Args>
void doFunc(Args ... args)
{
std::any_cast<std::function<void(Args...)>>(callbackFunc)(std::move(args)...);
}

这不是很好处理。不允许引用参数(未实现强制(,并且必须使用完全正确的类型传递参数,因为隐式转换无法通过此接口。因此,如果您注册void(int),则无法void(long)调用它。

如果尝试使用错误数量的参数进行调用,则会引发异常。

我的结论:没有简单的解决方案可以将具有不受约束的参数列表的函数存储到单个类型中。这种尝试当然不足以用于一般用途。