我使用 recursive_directory_iterator 来迭代目录。当传递的路径不存在时,迭代器似乎会抛出异常。有没有一种方法可以在不启用异常的情况下使用迭代器?
// try / catch can't be used here
for (auto const& dir_entry : fs::recursive_directory_iterator("I-dont-exist"))
{
std::cout << dir_entry << '\n';
}
采用 std::error_code& 参数的重载设置它 如果操作系统 API 调用失败,则返回操作系统 API 错误代码,并执行 ec.clear() 如果没有出现错误。
这个构造函数没有被标记为
noexcept
的原因很可能是因为,迂腐地,它可能会因为与不存在的目录或路径无关的原因而抛出异常。这只保证在文件系统问题(例如不存在的目录)的情况下不会出现异常。由于您希望防止因此原因引发异常,因此这应该可行。
您的下一个任务是构造
std::filesystem::path
而不抛出异常。
std::filesystem::path
构造函数定义如下:“可能抛出实现定义的异常”,如果他们愿意,出于任何原因,全权委托抛出异常。
但是,实际上,这是指有效路径的文件系统路径。尝试在 MS-Windows 上构建“/:\WINDOWS\SYSTEM”的路径可能会为您带来这些“实现定义”的异常之一。
如果您提供的路径字符串是操作系统上有效的路径字符串,则不会抛出异常。
最后,
std::filesystem::path
的构造函数是隐式的。对于您的用例,避免异常可以归结为:
构造递归目录迭代器时传递有效路径。您可以根据操作系统文件名的规则来验证它。
使用引用错误代码对象的重载作为附加参数。
我认为之前的任何一个答案都不能解决问题。
问题在于基于范围的 for 循环隐式使用operator++() 来递增迭代器。请参阅https://en.cppreference.com/w/cpp/language/range-for
但是,如果你想要非抛出迭代器,签名是
recursive_directory_iterator& increment( std::error_code& ec );
(参见 https://en.cppreference.com/w/cpp/filesystem/recursive_directory_iterator/increment)。
这意味着您需要编写一个老式的 for 循环。
类似这样的事情
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)) {