在 Qt 5 中重用现有的 QDirIterator
Reuse existing QDirIterator in Qt 5
我在 Qt 5 项目的单个范围内使用多个 QDirIterator
。它们通常看起来像这样:
QDirIterator i(QDir::currentPath(), QDir::Dirs | QDir::NoDotAndDotDot);
while (i.hasNext()) {
doSomething();
};
现在我使用多个对象,它们都有自己的名称(i0
、i1
、i2
等),我想知道如何在整个项目中只使用一个名称, i
在这个例子中?我应该如何停用现有 QDirIterator
以重新使用它?
C++ 允许您在任何需要的地方引入新的作用域,例如:
{
QDirIterator i(path1, QDir::Dirs | QDir::NoDotAndDotDot);
while (i.hasNext()) {
doSomething();
};
}
{
QDirIterator i(path2, QDir::Dirs | QDir::NoDotAndDotDot);
while (i.hasNext()) {
doSomething();
};
}
您可以实现前向顺序迭代器适配器 QDirIterator
:
// https://github.com/KubaO/Whosebugn/tree/master/questions/dir-iterator-39133673
#include <QtCore>
#include <boost/optional.hpp>
#include <boost/iterator/iterator_facade.hpp>
class QDir_iterator : public
boost::iterator_facade<QDir_iterator, QString,
boost::forward_traversal_tag, QString>
{
friend class boost::iterator_core_access;
boost::optional<QDirIterator &> it;
bool equal(const QDir_iterator & other) const {
return **this == *other;
}
QString dereference() const {
return it != boost::none ? it->filePath() : QString{};
}
void increment() {
it->next();
}
public:
QDir_iterator() = default;
QDir_iterator(QDirIterator & dir) : it{dir} {
it->next();
}
};
QDir_iterator begin(QDirIterator & dir) { return QDir_iterator{dir}; }
QDir_iterator end(QDirIterator &) { return QDir_iterator{}; }
适配器可用于 QDirIterator
,因此您可以将 QDirIterator
直接传递给范围:
void test1() {
auto curr = QDir::current();
auto entries = curr.entryList();
int i = 0;
for (auto dir : QDirIterator{curr}) ++i;
Q_ASSERT(i == entries.count());
}
当然,您可以将任何必要的标志或过滤器传递给 QDirIterator
。适配器将跟随它们。
如果你对 Boost 过敏,你可以考虑将目录迭代到 "save" 必须处理支撑范围:
template <typename F>
void iterate(QDirIterator && it, F && fun) {
while (it.hasNext())
fun(it.next());
}
迭代使用临时迭代器 - 统一初始化使其非常轻松:
void test2() {
auto curr = QDir::current();
auto entries = curr.entryList();
int i = 0, j = 0;
iterate({curr}, [&](const QString &){ ++i; });
Q_ASSERT(entries.length() == i);
iterate({curr}, [&](const QString &){ ++j; });
Q_ASSERT(entries.length() == j);
}
我在 Qt 5 项目的单个范围内使用多个 QDirIterator
。它们通常看起来像这样:
QDirIterator i(QDir::currentPath(), QDir::Dirs | QDir::NoDotAndDotDot);
while (i.hasNext()) {
doSomething();
};
现在我使用多个对象,它们都有自己的名称(i0
、i1
、i2
等),我想知道如何在整个项目中只使用一个名称, i
在这个例子中?我应该如何停用现有 QDirIterator
以重新使用它?
C++ 允许您在任何需要的地方引入新的作用域,例如:
{
QDirIterator i(path1, QDir::Dirs | QDir::NoDotAndDotDot);
while (i.hasNext()) {
doSomething();
};
}
{
QDirIterator i(path2, QDir::Dirs | QDir::NoDotAndDotDot);
while (i.hasNext()) {
doSomething();
};
}
您可以实现前向顺序迭代器适配器 QDirIterator
:
// https://github.com/KubaO/Whosebugn/tree/master/questions/dir-iterator-39133673
#include <QtCore>
#include <boost/optional.hpp>
#include <boost/iterator/iterator_facade.hpp>
class QDir_iterator : public
boost::iterator_facade<QDir_iterator, QString,
boost::forward_traversal_tag, QString>
{
friend class boost::iterator_core_access;
boost::optional<QDirIterator &> it;
bool equal(const QDir_iterator & other) const {
return **this == *other;
}
QString dereference() const {
return it != boost::none ? it->filePath() : QString{};
}
void increment() {
it->next();
}
public:
QDir_iterator() = default;
QDir_iterator(QDirIterator & dir) : it{dir} {
it->next();
}
};
QDir_iterator begin(QDirIterator & dir) { return QDir_iterator{dir}; }
QDir_iterator end(QDirIterator &) { return QDir_iterator{}; }
适配器可用于 QDirIterator
,因此您可以将 QDirIterator
直接传递给范围:
void test1() {
auto curr = QDir::current();
auto entries = curr.entryList();
int i = 0;
for (auto dir : QDirIterator{curr}) ++i;
Q_ASSERT(i == entries.count());
}
当然,您可以将任何必要的标志或过滤器传递给 QDirIterator
。适配器将跟随它们。
如果你对 Boost 过敏,你可以考虑将目录迭代到 "save" 必须处理支撑范围:
template <typename F>
void iterate(QDirIterator && it, F && fun) {
while (it.hasNext())
fun(it.next());
}
迭代使用临时迭代器 - 统一初始化使其非常轻松:
void test2() {
auto curr = QDir::current();
auto entries = curr.entryList();
int i = 0, j = 0;
iterate({curr}, [&](const QString &){ ++i; });
Q_ASSERT(entries.length() == i);
iterate({curr}, [&](const QString &){ ++j; });
Q_ASSERT(entries.length() == j);
}