带有成员函数的 QtConcurrent::map() = 无法编译

Posted

技术标签:

【中文标题】带有成员函数的 QtConcurrent::map() = 无法编译【英文标题】:QtConcurrent::map() with member function = can not compile 【发布时间】:2012-04-28 06:00:57 【问题描述】:

我的项目是创建一个小程序来演示搜索引擎的工作:为任意查询建立索引并返回结果。我已经完成了索引器部分的工作,现在我想通过一次索引多个文件来改进它。 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 的工作原理,文档也没有提供太多关于它的详细信息。我真的希望这里有人可以提供帮助。提前致谢。

【问题讨论】:

【参考方案1】:

为了能够调用指向成员的指针,除了函数形式参数之外,您还需要该类的实例(您在成员函数中获得的 this 指针)。

有两种方法可以处理这个问题:创建一个简单的函子来包装调用,或者使用 lambda。

仿函数看起来像这样:

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

你会像这样使用它:

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

(不过,请注意该包装器的生命周期。您可以使其更通用 - 例如,您还可以在包装器中存储一个指向成员的指针,和/或如果您想重用该结构,则将其设为模板其他类型。)

如果你有一个带有 lambda 的 C++11 编译器,你可以避免所有这些样板:

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

注意:我不确定QtConcurrent::MemberFunctionWrapper1 是如何参与您的示例的,我在这里没有看到。因此,对于这种情况,Qt 中可能已经有一个通用包装器,但我不知道。

【讨论】:

Indexer 类实际上是一个 AVL 树类。经过一些研究,我意识到我的实现不支持树上的并发操作。我真正需要的是一个放松平衡的 AVL 树。 我真的不明白这与您发布的具体问题有何关系。 对于我的具体问题,你的解决方案是对的。我可以愉快地使用 lambdas 编译我的代码。虽然我无法测试它,因为我的程序在函数中出现了段错误。 好的,谢谢。我想我可能错过了你的观点。不过,恐怕我对并发树结构了解不多,抱歉。

以上是关于带有成员函数的 QtConcurrent::map() = 无法编译的主要内容,如果未能解决你的问题,请参考以下文章

通过带有成员函数指针的 QHash 调用成员函数的正确方法

如何将带有 args 的成员函数作为参数传递给另一个成员函数?

如何声明一个带有指向成员函数的函数

指向带有 boost::variant 的成员函数的指针

使用带有模板参数的成员函数指针

如何创建带有参数的成员函数指针数组?