8

テンプレート関数を非同期に渡すにはどうすればよいですか?

コードは次のとおりです。

//main.cpp
#include <future>
#include <vector>
#include <iostream>
#include <numeric>

int
main
    ()
{      
    std::vector<double> v(16,1);

    auto r0 =  std::async(std::launch::async,std::accumulate,v.begin(),v.end(),double(0.0));

    std::cout << r0.get() << std::endl;
    return 0;
}

エラーメッセージは次のとおりです。

                                                                               ^
a.cpp:13:88: 注: 候補は:
a.cpp:1:0 からインクルードされたファイル:
/usr/include/c++/4.8/future:1523:5: 注意: テンプレート std::future::type> std::async(std::launch, _Fn&&, _Args&& ...)
     async(launch __policy, _Fn&& __fn, _Args&&... __args)
     ^
/usr/include/c++/4.8/future:1523:5: 注: テンプレート引数の推定/置換に失敗しました:
a.cpp:13:88: 注: テンプレート パラメータ '_Fn' を推測できませんでした
   auto r0 = std::async(std::launch::async,std::accumulate,v.begin(),v.end(),double(0.0));
                                                                                        ^
a.cpp:1:0 からインクルードされたファイル:
/usr/include/c++/4.8/future:1543:5: 注意: テンプレート std::future::type> std::async(_Fn&&, _Args&& ...)
     async(_Fn&& __fn, _Args&&... __args)
     ^
/usr/include/c++/4.8/future:1543:5: 注: テンプレート引数の推定/置換に失敗しました:
/usr/include/c++/4.8/future: 'template std::future::type> std::async(_Fn&&, _Args&& ...) の代わりに [with _Fn = std::launch; _Args = {}]':
a.cpp:13:88: ここから必要
/usr/include/c++/4.8/future:1543:5: エラー: 'type' という名前の型が 'class std::result_of' にありません
4

2 に答える 2

13

問題は、2 番目の引数をstd::asyncコンパイラに渡すには、式&std::accumulateを関数ポインタに変換する必要があることですが、関数テンプレートのどの特殊化が必要かがわからないことです。人間には、 の残りの引数で呼び出すことができるものが必要なのは明らかですasyncが、コンパイラはそれを認識せず、各引数を個別に評価する必要があります。

PiotrS. の答えが言うようにstd::accumulate、明示的なテンプレート引数リストまたはキャストを使用して、必要なものをコンパイラに伝えることができます。代わりに、代わりにラムダ式を使用することもできます。

std::async(std::launch::async,[&] { return std::accumulate(v.begin(), v.end(), 0.0); });

ラムダの本体内で、コンパイラは呼び出しのオーバーロード解決を実行するため、std::accumulateどちらstd::accumulateを使用するかが決まります。

于 2014-09-12T19:08:24.173 に答える
7

テンプレート引数を明示的に渡すか、 を使用してstatic_cast、可能なインスタンス化を明確にする必要があります。

auto r0 = std::async(std::launch::async
                     , &std::accumulate<decltype(v.begin()), double>
                     , v.begin()
                     , v.end()
                     , 0.0);

また:

auto r0 = std::async(std::launch::async
       , static_cast<double(*)(decltype(v.begin()), decltype(v.end()), double)>(&std::accumulate)
       , v.begin()
       , v.end()
       , 0.0);
于 2014-09-12T18:58:10.783 に答える