17

以下のコードは、.then()タイプの継続の実装に関するHerbSutterアイデアに基づいています。

  template<typename Fut, typename Work>
auto then(Fut f, Work w)->std::future<decltype(w(f.get()))>
  { return std::async([=] { w(f.get()); }); }

これはauto next = then(f, [](int r) { go_and_use(r); });、同様に使用されます。

これは素晴らしいアイデアですが、現状では機能しません(将来は移動のみでコピー可能ではありません)。私が推測できる限り、c ++の今後のバージョンに表示される可能性が高いため、このアイデアは気に入っています(ただし、.then()または待機している場合もあります)。

先物を共有または類似させる前に、スタックオーバーフローコミュニティは、特に改善と提案(共有された先物でさえ)でこの実装をどのように考えるでしょうか?

提案を事前に感謝します。

(これは、スレッドのコストがかかるため、標準ベースのメカニズムが存在するまでの修正であることを認識しています(多分)))。

4

2 に答える 2

9

上記の実装には3つの問題があります。

  • std::shared_futureとして渡した場合にのみ機能しますFut
  • 継続は、例外を処理する機会を必要とする場合があります。
  • 指定std::launch::asyncしないと延期される可能性があるため、常に期待どおりに動作するとは限りません。したがって、継続は期待どおりに呼び出されません。

私はこれらに対処しようとしました:

template<typename F, typename W, typename R>
struct helper
{
    F f;
    W w;

    helper(F f, W w)
        : f(std::move(f))
        , w(std::move(w))
    {
    }

    helper(const helper& other)
        : f(other.f)
        , w(other.w)
    {
    }

    helper(helper&& other)
        : f(std::move(other.f))
        , w(std::move(other.w))
    {
    }

    helper& operator=(helper other)
    {
        f = std::move(other.f);
        w = std::move(other.w);
        return *this;
    }

    R operator()()
    {
        f.wait();
        return w(std::move(f)); 
    }
};

}

template<typename F, typename W>
auto then(F f, W w) -> std::future<decltype(w(F))>
{ 
    return std::async(std::launch::async, detail::helper<F, W, decltype(w(f))>(std::move(f), std::move(w))); 
}

このように使用されます:

std::future<int> f = foo();

auto f2 = then(std::move(f), [](std::future<int> f)
{
    return f.get() * 2; 
});
于 2013-01-07T17:21:00.893 に答える
-1

g++4.8およびclang++3.2でテストされたソリューションは次のとおりです。

template<typename F, typename W>
auto then(F&& f, W w) -> std::future<decltype(w(f.get()))>
{
  cout<<"In thread id = "<<std::this_thread::get_id()<<endl;
  return std::async(std::launch::async, w, f.get());
}

void test_then()
{
  std::future<int> result=std::async([]{ return 12;});
  auto f = then(std::move(result), [](int r) {
    cout<<"[after] thread id = "<<std::this_thread::get_id()<<endl;
    cout<<"r = "<<r<<endl;
    return r*r;
  });
  cout<<"Final result f = "<<f.get()<<endl;
}
于 2013-05-20T02:17:15.483 に答える