3

QtConcurrent::run 関数の前にある可変個引数テンプレート関数を作成して、いくつかの処理を行ってからパラメーターを渡すことを望んでいました。

QtConcurrent::run は非常にオーバーロードされています - qtconcurrentrun.hをチェックしてください

QtConcurrent::run に渡される、呼び出すことができる可変個引数テンプレート関数を作成することは可能ですか? これは私がこれまでに持っているものです:

template <typename returnT, typename... Args>
static auto Run(Args&&... args) -> QFuture<returnT>
{
     // Do Stuff

     // Now call through to start the task
     QFuture<returnT> future = QtConcurrent::run(std::forward<Args>(args)...);

     QFutureWatcher<void>* futureWatcher = new QFutureWatcher<void>(); //A QFutureWatcher<void> is special, see QFutureWatcher QT docs.
     futureWatcher->setFuture(future);
     QObject::connect(futureWatcher, &QFutureWatcher<void>::finished, [=]() { 
        // Do stuff
        futureWatcher->deleteLater();
     });
     return future;
  }

戻り値の型を推測する方法を見つけるのに苦労しているので、別のテンプレート パラメータとして returnT を取得しました。これは、次のコマンドで呼び出された場合にコンパイルされません (VS2012 Nov CTP):

Tasking::TaskManager::Run<void>([&]() { while (stopTask == false); });

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

1> error C2065: '<lambda_86e0f4508387a4d4f1dd8316ce3048ac>' : undeclared identifier
1>          Implementation\TaskingTests\TaskManagerTests.cpp(31) : see reference to function template instantiation 'QFuture<void> Tasking::TaskManager::Run<void,TaskManagerTests::WaitsForTaskTest::<lambda_86e0f4508387a4d4f1dd8316ce3048ac>>(TaskManagerTests::WaitsForTaskTest::<lambda_86e0f4508387a4d4f1dd8316ce3048ac> &&)' being compiled
1>C:\tkbt\Launch2.0.0\ICDE\IceLibrary\Implementation\Tasking/TaskManager.hpp(108): error C2974: 'std::forward' : invalid template argument for '_Ty', type expected
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\type_traits(1780) : see declaration of 'std::forward'
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\type_traits(1774) : see declaration of 'std::forward'
1>C:\tkbt\Launch2.0.0\ICDE\IceLibrary\Implementation\Tasking/TaskManager.hpp(108): error C2780: 'QFuture<T> QtConcurrent::run(const Class *,T (__cdecl Class::* )(Param1,Param2,Param3,Param4,Param5) const,const Arg1 &,const Arg2 &,const Arg3 &,const Arg4 &,const Arg5 &)' : expects 7 arguments - 0 provided
1>          c:\qt\qt5.0.2\5.0.2\msvc2012_64\include\qtconcurrent\qtconcurrentrun.h(333) : see declaration of 'QtConcurrent::run'

どんな助けでも大歓迎です。

4

1 に答える 1

1

それTaskManager.hpp(108)があなたが電話する回線だと思いますQtConcurrent::run

あなたが経験しているのは、この MSVC バグのようです。つまり、可変個引数テンプレートは MSVC でラムダを転送できません。この場合、おそらく最初のいくつかの引数に対して、oldscool ファンクターを使用するか、ラムダをサポートするために非可変個のオーバーロードを提供する必要があります。推測QtConcurrent::runする必要がある場合、 の最初の引数は関数でなければならず、他の引数はそのパラメーターである必要があると思います。つまり、Run引数なしで呼び出すことはできません。関数テンプレートを書き直して、関数の 1 つの固定 "通常" パラメーターと、関数の引数のパラメーター パックを使用することができます。

戻り値の型推論には、decltype を使用することをお勧めします。一緒にすると、次のようになります。

template <class F, class... Args>
static auto Run(F&& f, Args&&... args) 
  -> decltype(QtConcurrent::run(std::forward<F>(f), std::forward<Args>(args)...))
{
  auto future = QtConcurrent::run(std::forward<F>(f), std::forward<Args>(args)...);

  //I suppose this can not be a smart pointer?
  auto futureWatcher = new QFutureWatcher<void>(); 

  futureWatcher->setFuture(future);
  QObject::connect(futureWatcher, &QFutureWatcher<void>::finished, [=]() { 
    // Do stuff
    futureWatcher->deleteLater();
  });
  return future;
}

このようにして、ラムダは通常のテンプレート パラメータ F に渡されます。これは転送に問題がないはずです。つまり、この方法ではバグは発生しません。

更新:正しい戻り値の型がすぐに得られないQtConcurrent::run場合は、関数とその引数で decltype を使用できます。

static auto Run(F&& f, Args&&... args) 
  -> QtFuture<decltype(f(std::forward<Args>(args)...))>

std::remove_referenceおそらく、適切な将来の型を取得するために、いくつかのandstd::remove_constを decltype に追加する必要があります。

于 2013-07-02T06:30:55.417 に答える