Reputation: 21087
In C++17 it became easy to iterate over the items in some directory dir
:
for ( auto& dirEntry: std::filesystem::directory_iterator(dir) )
{
if ( !dirEntry.is_regular_file() ) continue;
...
Unfortunately this way may throw exceptions, which I want to avoid in my program.
The iteration without throwing exceptions is also possible:
std::error_code ec;
const std::filesystem::directory_iterator dirEnd;
for ( auto it = std::filesystem::directory_iterator( dir, ec ); !ec && it != dirEnd; it.increment( ec ) )
{
if ( !it->is_regular_file( ec ) ) continue;
...
but it is much wordier in C++. For example, I cannot use range based for. And this larger code size is really significant for me since I have a lot of places with iteration. Is there a way to simplify the code iterating directory items and still avoid exceptions?
Upvotes: 1
Views: 912
Reputation: 21087
I think one can create a safe wrapper iterator, which operator ++ will not throw an exception, as follows
// object of this struct can be passed to range based for
struct safe_directory
{
std::filesystem::path dir;
std::error_code & ec;
};
//iterator of directory items that will save any errors in (ec) instead of throwing exceptions
struct safe_directory_iterator
{
std::filesystem::directory_iterator it;
std::error_code & ec;
safe_directory_iterator & operator ++() { it.increment( ec ); return * this; }
auto operator *() const { return *it; }
};
safe_directory_iterator begin( const safe_directory & sd )
{
return safe_directory_iterator{ std::filesystem::directory_iterator( sd.dir, sd.ec ), sd.ec };
}
std::filesystem::directory_iterator end( const safe_directory & )
{
return {};
}
bool operator !=( const safe_directory_iterator & a, const std::filesystem::directory_iterator & b )
{
return !a.ec && a.it != b;
}
Then it can be used in a program like that
int main()
{
std::error_code ec;
safe_directory sdir{ std::filesystem::current_path(), ec };
for ( auto dirEntry : sdir )
{
if ( dirEntry.is_regular_file( ec ) )
std::cout << dirEntry.path() << std::endl;
}
}
See example in online compiler: https://gcc.godbolt.org/z/fb4qPE6Gf
Upvotes: 1