用索引映射QTL
我想知道是否有一个选项也可以使用用索引映射QTL,qt,dictionary,indexing,qthread,qtconcurrent,Qt,Dictionary,Indexing,Qthread,Qtconcurrent,我想知道是否有一个选项也可以使用QtConcurrent::mapped(someVector和someFunction))(也可以是filter,filtered,map,…) 我想要的:我想要根据someVector中的当前索引对someVector中的元素做一些事情。但是由于函数someFunction仅采用类型T,该类型也用于QVector向量 我所做的:因为我需要它,我创建了一个QVector,并手动为元素创建了索引 因为这需要更多的空间,而且不是一个好的解决方案,我想可能还有另一个解
QtConcurrent::mapped(someVector和someFunction))
(也可以是filter
,filtered
,map
,…)
我想要的:我想要根据someVector中的当前索引对someVector中的元素做一些事情。但是由于函数someFunction
仅采用类型T
,该类型也用于QVector向量
我所做的:因为我需要它,我创建了一个QVector
,并手动为元素创建了索引
因为这需要更多的空间,而且不是一个好的解决方案,我想可能还有另一个解决方案
文档:如果您的输入是QVector
,您可以利用QVector
连续存储所有元素的事实。这意味着,给定对QVector v
中元素e
的引用,则e
的索引可通过以下方式获得:
std::ptrdiff_t idx = &e - &v.at(0);
下面是使用QtConcurrent::mapped
的完整示例:
#include <iterator>
#include <numeric>
#include <type_traits>
#include <utility>
#include <QtCore>
#include <QtConcurrent>
// lambda functions are not directly usable in QtConcurrent::mapped, the
// following is a necessary workaround
// see https://stackoverflow.com/a/49821973
template <class T> struct function_traits :
function_traits<decltype(&T::operator())> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
// specialization for pointers to member function
using functor_type = ClassType;
using result_type = ReturnType;
using arg_tuple = std::tuple<Args...>;
static constexpr auto arity = sizeof...(Args);
};
template <class Callable, class... Args>
struct CallableWrapper : Callable, function_traits<Callable> {
CallableWrapper(const Callable &f) : Callable(f) {}
CallableWrapper(Callable &&f) : Callable(std::move(f)) {}
};
template <class F, std::size_t ... Is, class T>
auto wrap_impl(F &&f, std::index_sequence<Is...>, T) {
return CallableWrapper<F, typename T::result_type,
std::tuple_element_t<Is, typename T::arg_tuple>...>(std::forward<F>(f));
}
template <class F> auto wrap(F &&f) {
using traits = function_traits<F>;
return wrap_impl(std::forward<F>(f),
std::make_index_sequence<traits::arity>{}, traits{});
}
int main(int argc, char* argv[]) {
QCoreApplication app(argc, argv);
// a vector of numbers from 0 to 500
QVector<int> seq(500, 0);
std::iota(seq.begin(), seq.end(), 0);
qDebug() << "input: " << seq;
QFuture<int> mapped = QtConcurrent::mapped(seq, wrap([&seq](const int& x) {
// the index of the element in a QVector is the difference between
// the address of the first element in the vector and the address of
// the current element
std::ptrdiff_t idx = std::distance(&seq.at(0), &x);
// we can then use x and idx however we want
return x * idx;
}));
qDebug() << "output: " << mapped.results();
QTimer::singleShot(100, &app, &QCoreApplication::quit);
return app.exec();
}
#包括
#包括
#包括
#包括
#包括
#包括
//lambda函数在QtConcurrent::mapped中不能直接使用
//以下是一个必要的解决方法
//看https://stackoverflow.com/a/49821973
模板结构函数特性:
功能{};
模板
结构功能特性{
//成员函数指针的专门化
使用函子_type=ClassType;
使用结果类型=返回类型;
使用arg_tuple=std::tuple进行相关讨论。请注意,链接的问题有一个更清晰的答案,包括使用boost中的zip和计数迭代器(或者可能是它们的C++20范围对应项),但我认为当map
将序列切片为块,并将这些块分配给多个线程时,这对QtConcurrent::map
不起作用。如果元素需要知道其在container@vladimir,我不同意。将容器作为编号序列处理没有问题元素的影响。这是一种非常常见的模式,它起作用。