+-
Qt::Concurrent映射了一个成员函数。

我想使用 QtConcurrent::mapped() 函数,但通过 QtConcurrent例子 提供的,并且试图找到一个可用的例子来扩展到我的使用中是很困难的。

在例子中,Qt 地图 到静态函数,没有使用成员函数(在例子中发现许多模拟映射的变化,但没有使用成员函数)。

的问题。

QtConcurrent::map() 将一个函数应用于Sequence或Iterator wo返回即: QFuture<void>. 然而,我希望返回的结果是,即 QFuture<SomeStructOrType> 从一个成员函数中返回。

我想使用它的例子是一个UI应用程序中的密集型工作负载,但一个模拟的例子可以是。

class MainWindow : public QMainWindow {
     Q_OBJECT

  public:
     // The struct is to demonstrate a datatype more complex than int / QString
     struct IntStruct {
         int i;
     };

     MainWindow(QWidget* parent = nullptr);
     IntStruct doubleValue(IntStruct i);
     ~MainWindow();

private:
   Ui::MainWindow* ui;
   // To watch progress and act upon progress change
   QFutureWatcher<IntStruct> futureWatcher;

   // Member to keep track of mapped process
   QFuture<IntStruct> future;

   //...
}

实现方式是:

MainWindow::MainWindow(QWidget* parent)
     : QMainWindow(parent)
     , ui(new Ui::MainWindow)
{
     ui->setupUi(this);

     // Input Sequence/Iterator to perform doubleValue function on
     QList<IntStruct> intList = QList<IntStruct>();
     for (int i = 0; i < 1000; i++) {
         IntStruct s;
         s.i = qrand();
         intList.append(s);
     }

     // Watch future and report on result ready (process a result when done)
     connect(&futureWatcher, &QFutureWatcher<IntStruct>::resultReadyAt, this, [intList](int index){
         qDebug() << QString("[index = %1] value = %2").arg(QString::number(index), QString::number(intList.at(index).i));
     });

     //typedef IntStruct (MainWindow::*doubleValueFunction)(IntStruct);
     //doubleValueFunction memberFunction = this->doubleValue;             // this->doubleValue error: reference to non-static member function must be called ???

     // Run future - this doubleValue function should be a pointer to an instance function, how to do so?         
     future = QtConcurrent::mapped(intList, &MainWindow::doubleValue);
     futureWatcher.setFuture(future);
}

// Some complex member function
MainWindow::IntStruct MainWindow::doubleValue(MainWindow::IntStruct i)
{
    i.i *= i.i;
    return i;
}

我知道QtConcurrent允许使用lambdas, 但是我需要利用一个成员函数来代替。

我也尝试用lambda来使用指向当前实例的指针,但它给了我一个错误的schpiel,你可以找到这样的错误 此处.

 future = QtConcurrent::mapped(intList, [this](IntStruct &i){
     this->doubleValue(i);
 });

TL;DR基本上,我如何才能使用 QtConcurrent::mapped()的成员函数(最好是非lambda版本)?

对Bounty问题的更新

一些额外的信息。

这在屏幕上显示

enter image description here

当我尝试编译时,错误日志。

..\ThreadTester\mainwindow.cpp: In constructor 'MainWindow::MainWindow(QWidget*)':
..\ThreadTester\mainwindow.cpp:27:69: error: no match for 'operator=' (operand types are 'QFuture<MainWindow::IntStruct>' and 'QFuture<void>')
      future = QtConcurrent::mapped(intList, &MainWindow::doubleValue);
                                                                     ^
In file included from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/QFuture:1:0,
                 from ..\ThreadTester\thread.h:10,
                 from ..\ThreadTester\mainwindow.h:6,
                 from ..\ThreadTester\mainwindow.cpp:1:
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note: candidate: QFuture<MainWindow::IntStruct>& QFuture<MainWindow::IntStruct>::operator=(const QFuture<MainWindow::IntStruct>&)
 class QFuture
       ^~~~~~~
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note:   no known conversion for argument 1 from 'QFuture<void>' to 'const QFuture<MainWindow::IntStruct>&'
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note: candidate: QFuture<MainWindow::IntStruct>& QFuture<MainWindow::IntStruct>::operator=(QFuture<MainWindow::IntStruct>&&)
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtCore/qfuture.h:59:7: note:   no known conversion for argument 1 from 'QFuture<void>' to 'QFuture<MainWindow::IntStruct>&&'
In file included from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentfilterkernel.h:48:0,
                 from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/qtconcurrentfilter.h:47,
                 from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/QtConcurrent:8,
                 from ..\ThreadTester\thread.h:11,
                 from ..\ThreadTester\mainwindow.h:6,
                 from ..\ThreadTester\mainwindow.cpp:1:
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h: In instantiation of 'QtConcurrent::ThreadEngineStarter<T> QtConcurrent::startMapped(const Sequence&, Functor) [with T = void; Sequence = QList<MainWindow::IntStruct>; Functor = QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct>]':
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/qtconcurrentmap.h:132:88:   required from 'QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> QtConcurrent::mapped(const Sequence&, MapFunctor) [with Sequence = QList<MainWindow::IntStruct>; MapFunctor = MainWindow::IntStruct (MainWindow::*)(MainWindow::IntStruct); typename QtPrivate::MapResultType<void, MapFunctor>::ResultType = void]'
..\ThreadTester\mainwindow.cpp:27:69:   required from here
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h:237:71: error: could not convert 'QtConcurrent::startThreadEngine(ThreadEngine*) [with ThreadEngine = QtConcurrent::SequenceHolder1<QList<MainWindow::IntStruct>, QtConcurrent::MappedEachKernel<QList<MainWindow::IntStruct>::const_iterator, QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct> >, QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct> >; typename ThreadEngine::ResultType = MainWindow::IntStruct]()' from 'QtConcurrent::ThreadEngineStarter<MainWindow::IntStruct>' to 'QtConcurrent::ThreadEngineStarter<void>'
     return startThreadEngine(new SequenceHolderType(sequence, functor));
                                                                       ^
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h: In instantiation of 'bool QtConcurrent::MappedEachKernel<Iterator, MapFunctor>::runIteration(Iterator, int, QtConcurrent::MappedEachKernel<Iterator, MapFunctor>::T*) [with Iterator = QList<MainWindow::IntStruct>::const_iterator; MapFunctor = QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct>; QtConcurrent::MappedEachKernel<Iterator, MapFunctor>::T = MainWindow::IntStruct]':
..\ThreadTester\mainwindow.cpp:36:1:   required from here
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentmapkernel.h:175:17: error: no match for call to '(QtConcurrent::MemberFunctionWrapper1<MainWindow::IntStruct, MainWindow, MainWindow::IntStruct>) (const MainWindow::IntStruct&)'
         *result = map(*it);
In file included from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/qtconcurrentfilter.h:48:0,
                 from F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include\QtConcurrent/QtConcurrent:8,
                 from ..\ThreadTester\thread.h:11,
                 from ..\ThreadTester\mainwindow.h:6,
                 from ..\ThreadTester\mainwindow.cpp:1:
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentfunctionwrappers.h:132:14: note: candidate: T QtConcurrent::MemberFunctionWrapper1<T, C, U>::operator()(C&, U) [with T = MainWindow::IntStruct; C = MainWindow; U = MainWindow::IntStruct]
     inline T operator()(C &c, U u)
              ^~~~~~~~
F:\Qt\Qt5.13.1\5.13.1\mingw73_32\include/QtConcurrent/qtconcurrentfunctionwrappers.h:132:14: note:   candidate expects 2 arguments, 1 provided
mingw32-make[1]: *** [Makefile.Debug:1117: debug/mainwindow.o] Error 1
mingw32-make[1]: *** Waiting for unfinished jobs....
mingw32-make[1]: Leaving directory 'C:/Users/CybeX/QtProjects/build-ThreadTester-Desktop_Qt_5_13_1_MinGW_32_bit-Debug'
mingw32-make: *** [Makefile:38: debug] Error 2

对我来说完全没有意义的是: mapped() 返回一些数据类型U,如果我改变了 QFuture<IntStruct>QFuture<void>大家都很高兴,但我却没有收集到任何结果,这有违了我们的宗旨 mapped() 函数,但我想使用QtConcurrent::mapped()函数。

1
投票

你必须使用 std::bind:

#include <functional>

# ....

future = QtConcurrent::mapped(intList,
                              std::bind(&MainWindow::doubleValue,
                                        this,
                                        std::placeholders::_1));