Я надеялся создать шаблонную функцию с переменным числом аргументов, которая находится перед функциями 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); });
С верхней парой сообщений об ошибках:
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'
Любая помощь высоко ценится.
я Угадай тот TaskManager.hpp(108)
линия, по которой вы звоните QtConcurrent::run
,
Кажется, что вы испытываете эта ошибка MSVC. Короче говоря, шаблоны variadic не могут пересылать лямбды в MSVC. В этом случае вам, вероятно, придется использовать функтор oldscool или предоставить невариатические перегрузки для поддержки лямбд, возможно, для первых нескольких аргументов. Если бы я должен был догадаться, я бы подумал QtConcurrent::run
Первый аргумент должен быть функцией, а остальные аргументы являются ее параметрами, что означает, что вам никогда не придется вызывать Run
без аргументов. Вы можете переписать свой шаблон функции, чтобы иметь один фиксированный «нормальный» параметр для функции и пакет параметров для аргументов функции.
Для вывода типа возврата вы можете использовать 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
а также std::remove_const
к decltype, чтобы получить правильный тип будущего.
Других решений пока нет …