传递lambda表达式给创建async的函数
Pass lambda expression to function that creates async
我试图使一个类,通过独立异步消费函数。这是我的代码:
main.cpp
MPIAsyncPool pool;
MPIFuture val = pool.addTask(launch::async, [](int a) -> int {
return a;
}, 7);
cout << "Value: " << val.get() << endl;
MPIFuture v = pool.addTask(std::launch::async, doThings, 46);
cout << "Value: " << v.get() << endl;
MPIAsyncPool (.h& . cpp)
class MPIAsyncPool {
public:
MPIAsyncPool();
template<typename T, typename U>
MPIFuture addTask(std::launch, std::function<T(U...)> f, U...);
};
template<typename ReturnType, typename ArgsTypes>
MPIFuture MPIAsyncPool::addTask(std::launch launch, std::function<ReturnType(ArgsTypes...)> f, ArgsTypes... args) {
std::future<int> fut = std::async(launch, f, args);
return MPIFuture(fut.get());
}
声明似乎没问题,但我在定义签名方面遇到了一些问题。我错了吗?
这些是我得到的错误:
<>之前/home/query/clionprojects/MPIAsyncPool/main.cpp:在函数' int main(int, char**) '中:/home/query/clionprojects/MPIAsyncPool/main.cpp:17:15:错误:调用' MPIFuture::MPIFuture() '没有匹配的函数MPIFuture val;^/home/query/clionprojects/MPIAsyncPool/MPIAsyncPool.h:11:0从/home/quero/ClionProjects/MPIAsyncPool/main.cpp: 3:/home/query/clionprojects/MPIAsyncPool/MPIFuture .h:12:5: note: candidate: MPIFuture::MPIFuture(int)MPIFuture (int);^/home/query/clionprojects/MPIAsyncPool/MPIfuture.h:12:5:注意:candidate期望1个参数,提供0/home/query/clionprojects/MPIAsyncPool/MPIFuture .h:10:7:备注:candidate: constexpr MPIFuture::MPIFuture(const MPIFuture&)类MPIFuture {^/home/query/clionprojects/MPIAsyncPool/MPIfuture.h:10:7:注意:candidate期望1个参数,提供0/home/query/clionprojects/MPIAsyncPool/MPIFuture .h:10:7:备注:candidate: constexpr MPIFuture::MPIFuture(MPIFuture&&)/home/query/clionprojects/MPIAsyncPool/MPIfuture.h:10:7:注意:candidate期望1个参数,提供0/home/query/clionprojects/MPIAsyncPool/main.cpp:20:13:错误:调用' MPIAsyncPool::addTask(std::launch, main(int, char**)::, int) '时没有匹配的函数7)};^/home/query/clionprojects/MPIAsyncPool/main.cpp:3:0:/home/query/clionprojects/mpiasyncool/MPIAsyncPool.h:19:15:备注:candidate: template MPIFuture mpiasyncool::addTask(std::launch, std::function, U,…)MPIFuture addTask(std::launch, std::function f, U…);^/home/query/clionprojects/MPIAsyncPool/MPIAsyncPool.h:19:15:注意:模板参数演绎/替换失败:/home/query/clionprojects/MPIAsyncPool/main.cpp:20:13:注意:' main(int, char**):: '不是派生自' std::function '7)};^/home/query/clionprojects/mpiasyncool/main.cpp:22:64:错误:调用' mpiasyncool::addTask(std::launch, int (&)(int), int) '时没有匹配的函数MPIFuture v = pool。addTask(std::launch::async, doThings, 46);^/home/query/clionprojects/MPIAsyncPool/main.cpp:3:0:/home/query/clionprojects/mpiasyncool/MPIAsyncPool.h:19:15:备注:candidate: template MPIFuture mpiasyncool::addTask(std::launch, std::function, U,…)MPIFuture addTask(std::launch, std::function f, U…);^/home/query/clionprojects/MPIAsyncPool/MPIAsyncPool.h:19:15:注意:模板参数演绎/替换失败:/home/query/clionprojects/MPIAsyncPool/main.cpp:22:64:注意:不匹配的类型' std::function '和' int (*)(int) 'MPIFuture v = pool。addTask(std::launch::async, doThings, 46);^/home/query/clionprojects/MPIAsyncPool/MPIAsyncPool.cpp:14:109:错误:扩展模式argtypes不包含参数包MPIFuture MPIAsyncPool::addTask(std::launch launch, std::function f, argstype…)args) {^/home/query/clionprojects/mpiasyncool/mpiasyncool .cpp:14:11:错误:原型' MPIFuture mpiasyncool::addTask(std::launch, std::function) '不匹配任何类' mpiasyncool 'MPIFuture MPIAsyncPool::addTask(std::launch launch, std::function f, argstype…)args) {^/home/query/clionprojects/MPIAsyncPool/MPIAsyncPool.cpp:5:0:/home/query/clionprojects/mpiasyncool/MPIAsyncPool.h:19:15: error: candidate is: template MPIFuture mpiasyncool::addTask(std::launch, std::function, U,…)MPIFuture addTask(std::launch, std::function f, U…);std::function
是一种类型,其目的是类型擦除,允许您在相同类型的存储中存储多种类型的可调用值。你不能这样做。
模板类型推导是指从函数调用的实参中推导模板形参时发生的情况。你正在做这件事。
类型擦除和类型演绎是的逆。您的代码试图推断要擦除的类型,这在实际中不起作用,在理论上也很少有意义。
并且,类型擦除也在std::async
中发生:类型擦除的每一层都有成本(运行时间和编译时间),所以只有当您需要在同一个变量中存储多个类型的信息时才使用它。
这是你的代码的第一次传递:
class MPIAsyncPool {
public:
MPIAsyncPool();
// R is the return type of F when invoked with Us...
template<class F, class...Us, class R=typename std::result_of<F&(Us...)>::type>
MPIFuture addTask(std::launch, F&& f, Us&&...);
};
也在.h文件中:
template<class F, class...Us, class R>
MPIFuture MPIAsyncPool::addTask(std::launch launch, F&& f, Us...us) {
std::future<R> fut = std::async(launch, std::forward<F>(f), std::forward<Us>(us)...);
return MPIFuture(fut.get());
}
现在,这仍然很糟糕,因为当你return
时,你的阻塞了异步的。async的全部意义在于,除非你需要它,否则不要阻塞。
改变:
return MPIFuture(fut.get());
return MPIFuture(std::move(fut));
这可能需要修复MPIFuture
,但这是有意义的签名。您希望获取std::future
的状态,而不是block,并获取其值。
最后,您不能在.cpp文件中定义模板并在.cpp文件之外使用它们。这里是类型擦除的用法!
如果你真的想把实现放在.cpp
文件中,并且愿意将你的代码限制为返回int
的代码,我们可以这样做:
class MPIAsyncPool {
public:
MPIAsyncPool();
template<class F, class...Us, class R=typename std::result_of<F&(Us...)>::type>
MPIFuture addTask(std::launch l, F f, Us...us) {
// does not support move-only f or us...:
return addTaskInternal(l, [=]()->int{
return std::move(f)(std::move(us)...);
});
}
private:
MPIFuture addTaskInternal(std::launch, std::function<int()>);
};
. cpp :
MPIFuture MPIAsyncPool::addTask(std::launch launch, std::function<int()> f) {
std::future<int> fut = std::async(launch, std::move(f));
return MPIFuture(std::move(fut));
}
现在头文件转发到内部方法,该方法使用非模板签名。我们对lambda进行类型擦除,这样我们所记得的就是如何调用它、销毁它和复制它。这种擦除使得将其转换为"普通"方法(而不是模板方法)成为可能。
您没有发布确切的错误,但我猜这是因为您不使用可变模板,就像您应该的那样。addTask
签名应该是这样的:
template<typename T, typename... U>
MPIFuture addTask(std::launch, std::function<T(U...)> f, U...);
同时,你必须在函数实现中展开参数:
std::future<int> fut = std::async(launch, f, args...);
另外,我会移动参数而不是将它们作为值传递。整体实现应该如下所示:
template<typename ReturnType, typename... ArgsTypes>
MPIFuture MPIAsyncPool::addTask(std::launch launch, const std::function<ReturnType(ArgsTypes...)>& f, ArgsTypes&&... args) {
std::future<int> fut = std::async(launch, f, std::forward<Args>(args)...);
return MPIFuture(fut);
}
- 为什么std::async使用同一个线程运行函数
- 为什么我不能将引用作为 std::async 的函数参数传递
- async中没有匹配的函数(模板中未解析的类型)
- 在Visual Studio中,与std::async一起使用时不调用"thread_local"变量"析构函数,这是一个错误吗?
- C++从 std::async 函数读取命名空间中的全局变量标志
- 如何将函数及其参数传递给成员函数内的 std::async
- 使用 std::async 调用模板函数的正确方法是什么?
- 为什么不能将std :: async用于接收对抽象类作为参数的函数
- 没有与参数列表匹配的重载函数"async"实例
- 通过 std::async 启动的函数引发的异常会发生什么情况
- 如何在成员函数上使用 std::async
- std::async 和 lambda 函数在C++中没有给出关联的状态
- 如何使用“std::async”在互斥锁保护循环中调用函数
- 如何将函数参数传递给boost::async()
- std::async, std::函数对象和带有'callable'参数的模板
- std::async 可以与模板函数一起使用吗?
- 如何为返回async结果的函数指定函数签名
- 将std::async与模板函数结合使用
- 用std::async调用带unique_ptr类型的函数
- Boost async函数编译错误