`std::filesystem::directory_iterator` graceful handling of non-existing dir

Viewed 240

I have the following code:

for (const auto& x : std::filesystem::directory_iterator(dir)) {
    // do stuff with x
}

dir might not exist, and I want to treat this case as if the dir is empty. I can't seem to come up with a nice option.

  • If I guard everything with try/catch, then I'll be catching the iteration code exceptions as well, I don't want that.
  • If I move std::filesystem::directory_iterator construction up and guard it with try/catch, it becomes verbose, and I'll have to re-throw all other exceptions (won't it screw up stack traces and such?).
  • If I use the non-throwing constructor of directory_iterator, I'll have to throw std::error_code for other errors. I'm not sure how to do that.
2 Answers

According to std::filesystem::directory_iterator's documentation it has both default and move constructors. So:

std::filesystem::directory_iterator iter;

try {
    iter=std::filesystem::directory_iterator{dir};
} catch(...)
{
    // catch it
}

for (const auto& x : iter) {
    // do stuff with x
}

There are std::filesystem::directory_iterator overloads that accept a std::error_code parameter. They will yield an instance that compares equal to the end iterator if an error occurs rather than throwing.

std::error_code ec;
for (const auto& x : std::filesystem::directory_iterator(dir, ec)) {
    // do stuff with x
}

won't throw if the directory doesn't exist or if the path is a file. (My understanding is that if the iterator has at least one match then operator* on the iterator could throw due to catastrophic filesystem corruption or similar though.)

Related