2016-08-24 9 views
0

Я использую несколько QDirIterator s в рамках одного проекта Qt 5. Они, как правило, выглядит следующим образом:Повторное использование существующего QDirIterator в Qt 5

QDirIterator i(QDir::currentPath(), QDir::Dirs | QDir::NoDotAndDotDot); 
while (i.hasNext()) { 
    doSomething(); 
}; 

Теперь я использую несколько объектов все с их собственными именами (i0, i1, i2 и т.д.), и мне интересно, как я могу использовать только одно имя по проекту, i в этом пример? Как мне перевести существующий QDirIterator для его повторного использования?

ответ

2

C++ позволяет ввести новую область в любом месте вам нужно, например:

{ 
    QDirIterator i(path1, QDir::Dirs | QDir::NoDotAndDotDot); 
    while (i.hasNext()) { 
    doSomething(); 
    }; 
} 
{ 
    QDirIterator i(path2, QDir::Dirs | QDir::NoDotAndDotDot); 
    while (i.hasNext()) { 
    doSomething(); 
    }; 
} 
+0

Работы, спасибо! Это лучший способ повторного использования идентификаторов? – TranslucentCloud

+2

Это зависит от контекста. Как правило, объем любой переменной не должен быть больше, чем нужно. В некоторых случаях может быть лучше перемещать повторяющиеся части в отдельную функцию. –

0

Вы можете реализовать прямой последовательный адаптер итератора к QDirIterator:

// https://github.com/KubaO/stackoverflown/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, вы можете вынесет перебор каталога «сохранить», чтобы иметь дело с рамно рамками:

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); 
}