3

私のプロジェクトは、検索エンジンの動作を示す小さなプログラムを作成することです: 任意のクエリに対してインデックスを作成し、結果を返します。インデクサー部分で作業を完了しましたが、複数のファイルを一度にインデックス付けして改善したいと考えています。MainWindow クラスは次のとおりです。

class MainWindow : public QMainWindow
{
    Q_OBJECT
    .....
private:
    Indexer * indexer;
    QStringList fileList;
    ....
    void index(QStringList list);
    void add(const QString &filename);
}

これは次の実装ですadd(同じファイルのインデックスを再度作成しないようaddにアクセスfileListする必要があるため、静的メソッドにすることはできません):

void MainWindow::add(const QString &filename)
{
    if (!fileList.contains(filename))
    {
        indexer->addDocument(filename.toStdString());
        fileList.append(filename);
        qDebug() << "Indexed" << filename;
        emit updatedList(fileList);
    }
}

メソッドの実装は、ファイル リストを受け取り、各ファイル名indexを呼び出すことです。add

void MainWindow::index(QStringList list)
{
    ....
    QtConcurrent::map(list, &MainWindow::add);
    ....
}

これらのコードをコンパイルするときに受け取るエラーは次のとおりです。

usr/include/qt4/QtCore/qtconcurrentmapkernel.h: In member function 'bool QtConcurrent::MapKernel<Iterator, MapFunctor>::runIteration(Iterator, int, void*) [with Iterator = QList<QString>::iterator, MapFunctor = QtConcurrent::MemberFunctionWrapper1<void, MainWindow, const QString&>]':
../search-engine/mainwindow.cpp:361:1:   instantiated from here
/usr/include/qt4/QtCore/qtconcurrentmapkernel.h:73:9: error: no match for call to '(QtConcurrent::MemberFunctionWrapper1<void, MainWindow, const QString&>) (QString&)'
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:128:7: note: candidate is:
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:138:14: note: T QtConcurrent::MemberFunctionWrapper1<T, C, U>::operator()(C&, U) [with T = void, C = MainWindow, U = const QString&]
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:138:14: note:   candidate expects 2 arguments, 1 provided

私は QtConcurrent がどのように機能するかについてあまり詳しくありません。また、ドキュメントには詳細が記載されていません。ここの誰かが助けてくれることを本当に願っています。前もって感謝します。

4

1 に答える 1

8

メンバーへのポインターを呼び出すことができるようにするには、その関数の仮引数に加えて、そのクラスのインスタンス(thisメンバー関数内で取得するポインター)が必要です。

これを処理するには、2つの方法があります。呼び出しをラップする単純なファンクターを作成するか、ラムダを使用します。

ファンクターは次のようになります。

struct AddWrapper {
  MainWindow *instance;
  AddWrapper(MainWindow *w): instance(w) {}
  void operator()(QString const& data) {
    instance->add(data);
  }
};

そして、あなたはそれを次のように使うでしょう:

AddWrapper wrap(this);
QtConcurrent::map(list, wrap);

(ただし、そのラッパーの存続期間に注意してください。より一般的なものにすることもできます。たとえば、ラッパーにメンバーへのポインターを格納したり、その構造を他のタイプで再利用したい場合はテンプレートにすることもできます。 。)

ラムダを使用するC++11コンパイラを使用している場合は、次のようなボイラーパルトをすべて回避できます。

QtConcurrent::map(list, [this] (QString const& data) { add(data); });

注:QtConcurrent::MemberFunctionWrapper1あなたの例にどのように関与したかはわかりません。ここでは表示されていません。したがって、この状況ではすでにQtに汎用ラッパーが存在する可能性がありますが、私はそれを認識していません。

于 2012-04-28T07:52:56.920 に答える