C++目录项迭代无异常
C++ directory item iteration without exceptions
在 C++17 中,迭代某些目录中的项目变得很容易 dir
:
for ( auto& dirEntry: std::filesystem::directory_iterator(dir) )
{
if ( !dirEntry.is_regular_file() ) continue;
...
不幸的是,这种方式可能会抛出异常,我想在我的程序中避免这种情况。
不抛异常的迭代也是可以的:
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;
...
但它在 C++ 中要冗长得多。例如,我不能使用基于范围的。这个更大的代码量对我来说真的很重要,因为我有很多地方需要迭代。
有没有办法简化代码迭代目录项并仍然避免异常?
我认为可以创建一个安全的wrapper迭代器,其中operator++不会抛出异常,如下
// 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;
}
然后就可以在类似的程序中使用了
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;
}
}
参见在线编译器中的示例:https://gcc.godbolt.org/z/fb4qPE6Gf
在 C++17 中,迭代某些目录中的项目变得很容易 dir
:
for ( auto& dirEntry: std::filesystem::directory_iterator(dir) )
{
if ( !dirEntry.is_regular_file() ) continue;
...
不幸的是,这种方式可能会抛出异常,我想在我的程序中避免这种情况。
不抛异常的迭代也是可以的:
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;
...
但它在 C++ 中要冗长得多。例如,我不能使用基于范围的。这个更大的代码量对我来说真的很重要,因为我有很多地方需要迭代。 有没有办法简化代码迭代目录项并仍然避免异常?
我认为可以创建一个安全的wrapper迭代器,其中operator++不会抛出异常,如下
// 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;
}
然后就可以在类似的程序中使用了
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;
}
}
参见在线编译器中的示例:https://gcc.godbolt.org/z/fb4qPE6Gf