Important: Please read the Qt Code of Conduct -

QtConcurrent::map with QList<Item*>

  • Hello folks,

    I want to use QtConcurrent::map for calling a member function (named extractFeatures) on every item of a QList. Unfortunately this doesn't work unless I change the list from QList<Item*> to QList<Item>. This is the code I wanted to use:

    QFutureWatcher<void> watcher_ = new QFutureWatcher<void>;
    > itemList = ...;

    watcher_->setFuture(QtConcurrent::map(itemList, &Item::extractFeatures));

    This is the error I get:
    @c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore/qtconcurrentmapkernel.h:73:9: error: no match for call to '(QtConcurrent::MemberFunctionWrapper<void, Item>) (Item*&)'
    c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore/qtconcurrentfunctionwrappers.h:119:14: note: candidate is: T QtConcurrent::MemberFunctionWrapper<T, C>::operator()(C&) [with T = void, C = Item]@

    Is there a way to call QtConcurrent::map() properly while maintaining the current data structure, that is, a QList of Item-Pointers?
    I would really appreciate any help. It's driving me mad.

  • The "documentation":/doc/qt-4.8/qtconcurrentmap.html#map says:

    bq. Calls function once for each item in sequence. The function is passed a reference to the item, so that any modifications done to the item will appear in sequence.

    So the map method calls your function with a refrerence-to-pointer argument. To make your function work, you must change its argument to and make it work with a reference-to-pointer of Item too:

    void Item::extractFeatures(Item *& item);
    @ and have some explanations.

  • Thank you very much for this hint.
    Actually the function does not take any arguments:
    @void Item::extractFeatures();@
    The idea of this function is to modify some instance members of the class.

    In fact I want to do something like this (from the "documentation":
    // squeeze all strings in a QStringList
    QStringList strings = ...;
    QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze);@
    QString::squeeze is a non-static void method of QString and it doesn't take any arguments, too.

  • Oh, you're right. I don't know if it's possible to call a member function on a reference-to-pointer with QtConcurrent. I would try to implement a wrapper method that calls the other method on the pointer. But that's just a blind guess, it may fail too.

  • Indeed this didn't work either. It seems as if it's not possible to use container of pointers with QtConcurrent.
    So I worked around this by iterating through the list and creating local copies of the items in a QList<Item>. This works though it's not very pretty. At least now I can take advantage of QtConcurrent and its automatic adjusting of the threads.
    Thank you anyway for your hints.

  • You could try to use an external method for the concurrent map:

    void extractFeaturesFromItem(Item *& item)
    // do your work on item here

    QFutureWatcher<void> watcher_ = new QFutureWatcher<void>;
    > itemList = ...;

    // use the above proxy method for the map:
    watcher_->setFuture(QtConcurrent::map(itemList, &extractFeaturesFromItem));

    It's not tested, just a wild guess again :)

  • it worked for me, thank you very much

Log in to reply