我一直在寻找problem of type-erasing a std::packaged_task
using std::function
的解决方法。
我想做的是这样的事情:
#include <future>
#include <functional>
#include <iostream>
namespace {
std::function<void()> task;
std::future<int> make(int val) {
auto test = std::packaged_task<int()>([val](){
return val;
});
auto fut = test.get_future();
task = std::move(test);
return fut;
}
}
int main() {
auto fut = make(100);
task();
std::cout << fut.get() << "\n";
}
它简洁明了,避免自己重新实施很多机制。不幸的是,这实际上并不合法,因为std::packaged_task
只是移动而不是可复制的。
作为一种解决方法,我想出了以下内容,它实现了std::promise
和std::shared_ptr
方面的内容:
#include <future>
#include <functional>
#include <iostream>
namespace {
std::function<void()> task;
std::future<int> make(int val) {
auto test = std::make_shared<std::promise<int>>();
task = [test,val]() {
test->set_value(val);
test.reset(); // This is important
};
return test->get_future();
}
}
int main() {
auto fut = make(100);
task();
std::cout << fut.get() << "\n";
}
这“对我有用”,但这实际上是正确的代码吗?有没有更好的方法来实现相同的净结果?
(请注意,第二个示例中std::shared_ptr
的生命周期对于我的实际代码非常重要。显然,我将采取措施防止两次调用相同的std::function
。
答案 0 :(得分:1)
您的问题似乎源于类型不兼容性:
std::function<void()> task; // Notice this is not a package_task
那你为什么期望这个有用?
task = std::move(test); // when test is `std::packaged_task<int()>`
当我将任务更改为正确的类型时,它会按预期编译:
namespace {
std::packaged_task<int()> task; // Change this.
std::future<int> make(int val) {
auto test = std::packaged_task<int()>([val](){
return val;
});
auto fut = test.get_future();
task = std::move(test); // This now compiles.
return fut;
}
}
就个人而言,因为类型很重要,我会从auto
删除test
。
namespace {
std::packaged_task<int()> task;
std::future<int> make(int val) {
std::packaged_task<int()> test([val](){return val;});
auto fut = test.get_future();
task = std::move(test);
return fut;
}
}