如何将未来移动到lambda表达式 [英] How to move future into lambda-expression

查看:162
本文介绍了如何将未来移动到lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Visual Studio 2013,我想实现这一行代码

I'm using Visual Studio 2013 and i want achieve this line of code

 f = p.get_future();
 auto task =[f = std::move(f)](){
   //use f
 };

我知道解决方案
这里,但不幸的是这不会编译VS2013(错误C2558没有可用的复制构造函数)。

I'm aware of the solution here, but unfortunately this doesn't compile under VS2013 (error C2558 no copy-constructor available).

推荐答案

您可以使用 shared_future 。这是最简单的。

You can use a shared_future. That is easiest.

但是,这并不能帮助你移动。如果你真的需要移动,我们可以使用 move_helper 函数和类的帮助:

However, that doesn't help you move. If you really need to move, we can do it with the help of a move_helper function and class:

template<class T, class F=void>
struct move_helper_t {
  T t;
  F f;
  template<class...Args>
  auto operator()(Args&&...args)
  ->typename std::result_of< F&(T&, Args...) >::type
  {
    return f(t, std::forward<Args>(args)...);
  }

  // force right-associativity of `->*`, and
  // invert the stack to get the arguments in the "right" order:
  template<class F1,
    class R0=move_helper_t< T, typename std::decay<F1>::type >
  >
  auto operator->*(F1&& f1)
  -> decltype(
    std::declval<F>()->*
    std::declval<R0>()
  )
  {
    return
      std::move(f)->*
      R0{ std::forward<T>(t), std::forward<F1>(f1) };
  }
};
template<class T>
struct move_helper_t<T,void> {
  T t;
  template<class F>
  auto operator->*(F&& f)
  -> move_helper_t<T, typename std::decay<F>::type>
  {
    return {std::forward<T>(t), std::forward<F>(f)};
  }
};

template<class T>
move_helper_t<std::decay_t<T>>
move_helper( T&& t ) {
  return {std::forward<T>(t)};
}

在MSVC 2013中,您可以构造函数在 move_helper_t 。我不记得他们的 return {} 代码是多么好。

In MSVC 2013 you may have to declare a constructor in move_helper_t. I do not recall how well written their return {} code was.

f = p.get_future();
task =
  move_helper(std::move(f)) ->*
  [](std::future<int>& f){
    //use f
  };

- > * c $ c> move_helper 到lambda。然后它返回一个可调用的对象,它将被调用时作为第一个参数传递 std :: future< int>&

->* binds the move_helper to the lambda. It then returns a callable object which will be passed the std::future<int>& as the first argument when invoked.

由于它的写法,你甚至可以链接它:

Because of how it is written, you can even chain it:

auto f = p.get_future();
auto f2 = p2.get_future();
task =
  move_helper(std::move(f)) ->*
  move_helper(std::move(f2)) ->*
  [](std::future<int>& f, std::future<char>& f2){
    //use f
  };

可将多个参数移入lambda。

to move more than one argument into the lambda.

在这两种情况下, task()可以调用任务 - - > * 操作绑定lambda并传递未来。

In both cases, task can be invoked by task() -- the ->* operation binds the lambda up and passes the futures when invoked.

现场示例

请注意,这解决了将未来移动到lambda。如果你想在一个 std :: function 中存储lambda,这个不会帮助你,因为函数必须是可复制的。

Note that this solves the problem of moving the future into the lambda. If you want to store the lambda in a std::function, this will not help you, as functions must be copyable.

template<class F>
struct shared_function {
  std::shared_ptr<F> pf;
  template<class ...Args>
  typename std::result_of<F&(Args...)>::type
  operator()(Args&&...args) const {
   return (*pf)(std::forward<Args>(args)...);
  }
};
template<class F,
  class dF=typename std::decay<F>::type
>
shared_function< dF >
make_shared_function( F&& f ) {
  return {std::make_shared<dF>(std::forward<F>(f))};
}

这需要一个可移动的lambda并将其包装在一个共享指针中, c $ c> operator()。但是首先通过上面的技术将一个未来移动到一个lambda,然后将这个lambda包装在一个共享函数中传递给一个 std: :function 是可笑的:只是首先使用 shared_future

this takes a movable lambda and wraps it in a shared pointer and exposes operator() for you. But first taking a future moving it into a lambda via the above technique, and then wrapping that lambda in a shared function to pass it to a std::function is ridiculous: just use a shared_future in the first place.

在理论上, packed_task 只需要移动,但我不确定MSVC2013是否支持这个要求。

As an aside, in theory, a packaged_task only requires move, but I am uncertain if MSVC2013 supports that requirement.

这篇关于如何将未来移动到lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆