Шаблон Variadic для прокси QtConcurrent :: run functions

Я надеялся создать шаблонную функцию с переменным числом аргументов, которая находится перед функциями 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'

Любая помощь высоко ценится.

2

Решение

я Угадай тот 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, чтобы получить правильный тип будущего.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]