I wanted to use the std::filesystem::recursive_directory_iterator
class to create a class method iterating through all subdirectories and processing found xml files.
The only way I have found on the internet to do this was using a for loop like this:
for (fs::directory_entry p : fs::recursive_directory_iterator("my_file"))
do_something(p);
The problem is that i need to store my iterator (or atleast where it's pointing) inbetween function calls as i can only process one file at a time. I tried implementing it like this:
class C {
private:
std::filesystem::recursive_directory_iterator it;
std::filesystem::directory_entry p;
public:
C(std::filesystem::path);
std::string find_file();
};
C::C(std::filesystem::path path)
{
it = fs::recursive_directory_iterator(path);
p = fs::directory_entry(it.begin());
}
std::string C::find_file()
{
do { //using do while so my function won't load the same file twice
++p;
} while (!is_xml(p.path()) && p != it.end());
}
But it seems that std::filesystem::recursive_directory_iterator
doesn't have begin()
and end()
methods and can't be compared.
I have no idea how my code is different from the working for range loop except for storing the iterator and having an extra condition.
If you look a std::filesystem::recursive_directory_iterator Non-member functions you can see that there is:
// range-based for loop support
begin(std::filesystem::recursive_directory_iterator)
end(std::filesystem::recursive_directory_iterator)
And then std::filesystem::begin(recursive_directory_iterator), std::filesystem::end(recursive_directory_iterator)
with more details:
end(recursive_directory_iterator)
Returns a default-constructed recursive_directory_iterator, which serves as the end iterator. The argument is ignored.
So you will check if it
is not equal to std::end(it)
, so see if there are any more elements. And you have to increment it
and not p
.
You also need to check if it != std::end(it)
before you do !is_xml(*it.path())
std::string C::find_file()
{
do { //using do while so my function won't load the same file twice
++it;
} while (it != std::end(it) && !is_xml(*it.path()));
}
recursive_directory_iterator
is already an iterator by itself (it says so right in its name), so you don't need to use begin()
and end()
at all. It implements operator==
, operator!=
, operator->
, and operator++
, which are all you need in this case.
Also, there is no reason for p
to be a class member at all. It should be a local variable of find_file()
instead (actually, in this case, it can be eliminated completely). And the loop should be a while
loop instead of a do..while
loop, in case the iterator is already at its "end" when find_file()
is entered.
Try this instead:
class C {
private:
std::filesystem::recursive_directory_iterator it;
public:
C(std::filesystem::path);
std::string find_file();
};
C::C(std::filesystem::path path)
: it(path)
{
}
std::string C::find_file()
{
static std::filesystem::directory_iterator end;
while (it != end) {
auto p = it->path();
if (is_xml(p))
return p.string();
++it;
}
return "";
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.