c – 结合QtConcurrent调用

我有三个方法,所有这些方法返回一个字符串,我想使用QtConcurrent运行所有这些方法,并将它们返回到单个列表或类似的东西. QtConcurrent :: mapped是理想的,因为它返回一个迭代器,但我只能运行一个方法.
JavaScript中有promise.all([method_a,method_b,method_c]),它会自动将它们的返回合并到一个结果(迭代器)中.
在Qt怎么做?

解决方法:

由于您有几种方法可以调用,因此您可以将它们作为一系列仿函数传递给QtConcurrent :: mapped的第一个参数.映射函子是一个应用函子,它接受一个表示方法调用的函子并返回调用它的结果.

首先,让我们上课:

// https://github.com/KubaO/*n/tree/master/questions/concurrent-combine-49802153
#include <QtConcurrent>
#include <functional>
#include <initializer_list>
#include <type_traits>

class Cls {
public:
   QString method1() const { return QStringLiteral("10"); }
   QString method2() const { return QStringLiteral("20"); }
   QString method3() const { return QStringLiteral("30"); }
};

apply_t仿函数调用作为参数传递给它的方法:

template <class Method> struct apply_t {
   using result_type = typename std::result_of_t<Method()>;
   auto operator()(Method method) {
      return method();
   }
};

让我们可以方便地从一系列仿函数的类型中制作这样的涂抹器:

template <class Sequence, class A = apply_t<typename std::decay_t<Sequence>::value_type>>
A make_apply(Sequence &&) { return {}; }

为方便起见,我们还将有一个矢量发生器,其目的是: make_unique等:

template <class T> QVector<T> make_vector(std::initializer_list<T> init) {
   return {init};
}

然后,问题变得相当简单.首先,我们创建一个将被调用的绑定方法的向量.然后我们将调用方法以及对它们进行操作的应用程序传递给QtConcurrent :: mapped. results()按顺序给出了方法调用的所有结果的列表.

int main() {
   Cls obj;
   auto const methods = make_vector({
                                 std::bind(&Cls::method1, &obj),
                                 std::bind(&Cls::method2, &obj),
                                 std::bind(&Cls::method3, &obj)
                              });
   QFuture<QString> result =
         QtConcurrent::mapped(methods, make_apply(methods));
   Q_ASSERT((result.results() == QStringList{"10", "20", "30"}));
}

我们可以使用lambda而不是创建自定义的apply_t类,并将其包装以提供QtConcurrent :: mapped期望的result_type成员类型.有关包裹lambda的详细信息,请参阅this answer. rest of this answer提供了这种包装的例子.

上一篇:反射简单介绍


下一篇:win10下QT5打包可执行程序