我的应用程序中有很多异步调用。它们从服务器检索数据并使用检索到的数据执行回调。我想按照以下方式处理它们:
这是我目前的做法:
template<typename... T>
void exec_async(std::function<void(T&...)> func, std::function<void(T&...)> callback, T... args)
{
std::future<void> result = std::async(std::launch::async, [&]
{
func(args...);
callback(args...);
});
}
void callback_func(const std::string& output)
{
std::cout << "Output: " << output << std::endl;
}
void exec_func()
{
auto func = [](std::string& in)
{
in = "testing";
};
exec_async<std::string>(func, &callback_func, "");
}
这种方法效果很好,但要使用它,我必须在
func
和 callback
之后传递一组默认变量。理想情况下我不必这样做。如何使用这种方法但不必指定默认变量?
即 exec_async<std::string>(func, &callback_func);
而不是 exec_async<std::string>(func, &callback_func, "");
理想情况下,我会初始化
exec_async
中的变量,将它们传递到 func
,然后传递到 callback
。像这样的东西:
template<typename... T>
void exec_async(std::function<void(T&...)> func, std::function<void(T&...)> callback)
{
T ...args;
std::future<void> result = std::async(std::launch::async, [&]
{
func(args...);
callback(args...);
});
}
但我无法编译这样的东西。正确的做法是什么?
这是正确的实现:
template<typename... T>
void exec_async(std::function<void(T&...)> func, std::function<void(T&...)> callback)
{
std::tuple<T...> args;
std::future<void> result = std::async(std::launch::async, [&]
{
std::apply(func, args);
std::apply(callback, args);
});
}
诚然,由 ChatGPT 提供。我不会费心去尝试这个。
解释为什么它有效(由我提供):
std::tuple
可以存储许多不同类型的变量。如果在函数中声明,则 T... args
不是有效的参数包。然而,模板完全可以接受T...
。在这里,使用所有必需的参数创建一个元组。 std::tuple
是默认初始化的,所以我不需要担心这一点。 std::apply
调用提供的函数,并将元组转换为参数列表。