将 packaged_task 移至 lambda
我想在 lambda 中移动并调用 boost::packaged_task 。
但是,我无法找出一个优雅的解决方案。
例如这不会编译。
template<typename Func>
auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept
{
typedef boost::packaged_task<decltype(func())> task_type;
auto task = task_type(std::forward<Func>(func));
auto future = task.get_future();
execution_queue_.try_push([=]
{
try{task();}
catch(boost::task_already_started&){}
});
return std::move(future);
}
int _tmain(int argc, _TCHAR* argv[])
{
executor ex;
ex.begin_invoke([]{std::cout << "Hello world!";});
//error C3848: expression having type 'const boost::packaged_task<R>' would lose some const-volatile qualifiers in order to call 'void boost::packaged_task<R>::operator ()(void)'
// with
// [
// R=void
// ]
return 0;
}
我相当丑陋的解决方案:
struct task_adaptor_t
{
// copy-constructor acts as move constructor
task_adaptor_t(const task_adaptor_t& other) : task(std::move(other.task)){}
task_adaptor_t(task_type&& task) : task(std::move(task)){}
void operator()() const { task(); }
mutable task_type task;
} task_adaptor(std::move(task));
execution_queue_.try_push([=]
{
try{task_adaptor();}
catch(boost::task_already_started&){}
});
将 packaged_task 移动到调用它的 lambda 中的“正确”方法是什么?
I want to move and call a boost::packaged_task inside a lambda.
However, I can't figure out an elegant solution.
e.g. This won't compile.
template<typename Func>
auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept
{
typedef boost::packaged_task<decltype(func())> task_type;
auto task = task_type(std::forward<Func>(func));
auto future = task.get_future();
execution_queue_.try_push([=]
{
try{task();}
catch(boost::task_already_started&){}
});
return std::move(future);
}
int _tmain(int argc, _TCHAR* argv[])
{
executor ex;
ex.begin_invoke([]{std::cout << "Hello world!";});
//error C3848: expression having type 'const boost::packaged_task<R>' would lose some const-volatile qualifiers in order to call 'void boost::packaged_task<R>::operator ()(void)'
// with
// [
// R=void
// ]
return 0;
}
My rather ugly solution:
struct task_adaptor_t
{
// copy-constructor acts as move constructor
task_adaptor_t(const task_adaptor_t& other) : task(std::move(other.task)){}
task_adaptor_t(task_type&& task) : task(std::move(task)){}
void operator()() const { task(); }
mutable task_type task;
} task_adaptor(std::move(task));
execution_queue_.try_push([=]
{
try{task_adaptor();}
catch(boost::task_already_started&){}
});
What is the "proper" way to move a packaged_task into a lambda which calls it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通过正确实现 std::bind (或与启用移动的类型等效的东西),您应该能够将 bind 和 C++0x lambda 结合起来,如下所示:
顺便说一句:您不需要 std::move围绕 future 因为 future 是一个本地对象。因此,它已经受到潜在的复制省略的影响,如果编译器无法执行该省略,则它必须从“未来”移动构造返回值。在这种情况下显式使用 std::move 实际上可能会抑制复制/移动省略。
With a proper implementation of std::bind (or something equivalent with respect to move-enabled types) you should be able to combine bind and a C++0x lambda like this:
btw: You don't need a std::move around future because future is a local object. As such, it's already subject to potential copy elision and if the compiler is not able to do that elision it has to move construct the return value from 'future'. The explicit use of std::move in this case may actually inhibit a copy/move elision.
我发布了一个关于转向 lambda 的类似问题。 C++0x 没有任何移动捕获语法。我能想到的唯一解决方案是某种代理函数对象。
请注意,我实际上并没有尝试过这段代码,如果使用可变参数模板,它会变得更好,但 MSVC10 没有它们,所以我不太了解它们。
There's a similar question up that I posted about moving into lambdas. C++0x doesn't have any move capture syntax. The only solution I could come up with was some kind of proxy function object.
Note that I haven't actually tried this code, and it would become a lot nicer with variadic templates, but MSVC10 doesn't have them so I don't really know about them.