Reputation: 1863
I use recursive_directory_iterator to iterate through directories. The iterator seems to throw exceptions when the passed path does not exist. Is there a way to use the iterator without enabling exceptions?
// try / catch can't be used here
for (auto const& dir_entry : fs::recursive_directory_iterator("I-dont-exist"))
{
std::cout << dir_entry << '\n';
}
Upvotes: 1
Views: 717
Reputation: 6906
I don't think that either of the previous answers address the problem.
The issue is that the range-based for loop implicitly uses operator++() to increment the iterator. See https://en.cppreference.com/w/cpp/language/range-for
However, if you want the non-throwing iterator, the signature is
recursive_directory_iterator& increment( std::error_code& ec );
(see https://en.cppreference.com/w/cpp/filesystem/recursive_directory_iterator/increment).
That means that you need to write an old-fashioned for loop.
Something like this
std::error_code ec;
using recursive_directory_iter =
std::filesystem::recursive_directory_iterator;
auto dirEntry = std::filesystem::begin(recursive_directory_iter(dir, ec));
for ( ; dirEntry != std::filesystem::end(recursive_directory_iter(dir, ec)); dirEntry.increment(ec)) {
Upvotes: 0
Reputation: 118292
From cppreference.com's writeup:
The overload taking a std::error_code& parameter sets it to the OS API error code if an OS API call fails, and executes ec.clear() if no errors occur.
The reason why this constructor is not marked noexcept
is most likely because, pedantically, it might throw an exception for reasons unrelated to a nonexistent directory or path. This only guarantees no exceptions in case of filesystem issues, such as your nonexistent directory. Since you are looking to prevent exceptions getting thrown for that reason, this should work.
Your next task is to construct std::filesystem::path
without throwing an exception.
std::filesystem::path
constructors are defined as follows: "May throw implementation-defined exceptions", a carte-blanche for throwing an exception if they fancy to, for any reason.
But, practically, this is referring to filesystem paths that are, well, valid paths. Attempting to construct a path for "/:\WINDOWS\SYSTEM" on MS-Windows will likely earn you one of those "implementation-defined" exceptions.
If you feed a path string that's a valid path string, on your operating system, you're not going to get a thrown exception.
Finally, std::filesystem::path
's constructors are implicit. Avoiding exceptions, for your use case, boils down to:
Passing a valid path when constructing a recursive directory iterator. It's up to you to validate it according to your operating system filenames' rules.
Using the overload that takes a reference to an error code object, as an additional parameter.
Upvotes: 1