我有三个方法,所有这些方法返回一个字符串,我想使用QtConcurrent运行所有这些方法,并将它们返回到单个列表或类似的东西. QtConcurrent :: mapped是理想的,因为它返回一个迭代器,但我只能运
在 JavaScript中有promise.all([method_a,method_b,method_c]),它会自动将它们的返回合并到一个结果(迭代器)中.
在Qt怎么做? 由于您有几种方法可以调用,因此您可以将它们作为一系列仿函数传递给QtConcurrent :: mapped的第一个参数.映射函子是一个应用函子,它接受一个表示方法调用的函子并返回调用它的结果.
首先,让我们上课:
// https://github.com/KubaO/stackoverflown/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提供了这种包装的例子.