由于您的错误是指递增recursive_filesystem_iterator,因此错误似乎来自for 语句本身,而不是您的后续代码。 for 语句在内部对 recursive_filesystem_iterator 执行增量 (operator++)。
对我来说,这感觉像是recursive_filesystem_iterator 的实现中的一个错误,您的代码应该可以正常工作。但是仔细阅读标准,我想有足够的模糊性让一个实现说你看到的行为仍然符合标准。
我没有 c++17 标准的正式副本,所以我在这里给出的参考是免费提供的草案 n4659.pdf。
30.10.2.1 Posix conformance,上面写着
Implementations that do not support exact POSIX behavior are encouraged to provide
behavior as close to POSIX behavior as is reasonable given the limitations of actual
operating systems and file systems. If an implementation cannot provide any reasonable
behavior, the implementation shall report an error as specified in 30.10.7. [Note:This
allows users to rely on an exception being thrown or an error code being set when an
implementation cannot provide any reasonable behavior.— end note]
Implementations are not required to provide behavior that is not supported by a
particular file system. [Example: The FAT file system used by some memory cards, camera
memory, and floppy disks does not support hard links, symlinks, and many other features
of more capable file systems, so implementations are not required to support those
features on the FAT file system but instead are required to report an error as described
above.— end example]
因此,如果底层文件系统不允许您这样做,尝试迭代到 D:\System Volume Information 可能会失败并引发异常。
您的构造函数指定directory_options::skip_permission_denied。我似乎这应该足以避免异常。
在30.10.14.1 recursive_directory_iterator members 中为operator++ 写着:
...then either directory(*this)->path() is recursively iterated into or, if
(options() & directory_options::skip_permission_denied) != directory_options::none
and an error occurs indicating that permission to access directory(*this)->path() is denied,
then directory(*this)->path() is treated as an empty directory and no error is reported.
您得到的实际异常并没有说“权限被拒绝”,所以我猜可能有人认为skip_permission_denied 选项不适用于它。这将允许operator++ 的实现在这种情况下抛出异常。我不喜欢这种解释,因为skip_permission_denied 的整个想法似乎是为了避免这样的异常。但这不取决于我。 :)
除了尝试将缺陷提交回您的标准库实现之外,您还能做什么?也许你可以写出一个老式的for 循环,并在recursive_filesystem_iterator 上使用increment 方法。 increment 方法返回错误代码而不是抛出异常。所以你的代码看起来像:
auto iter = fs::recursive_directory_iterator(dp, fs::directory_options::skip_permission_denied);
auto end_iter = fs::end(iter);
auto ec = std::error_code();
for (; iter != end_iter; iter.increment(ec))
{
if (ec)
{
continue;
}
// The rest of your loop code here...
}
我认为上面的内容看起来很合理,但绝对需要进行测试以确保不会出现一些奇怪的极端情况,即出现无限循环之类的情况。实际上,我不太确定是否需要 continue 的东西,但您可能想尝试一下。
最后,当您捕捉到filesystem_error 时,除了e.what() 之外,您还可以打印出e.path1.native()。我认为您已经大多知道该信息,因为您正在打印循环中的路径。但在某些情况下它可能会提供更多信息。