首页 > 解决方案 > 使用 fs::recursive_directory_iterator() 和 fs::directory_iterator() 的通用方法

问题描述

我需要递归或不迭代文件夹(给定布尔参数)。我发现有fs::recursive_directory_iterator()而且也有fs::directory_iterator()。在 Java 中,我希望它们实现相同的接口或共享共同的祖先,以便我可以替换所需的接口。但由于某种原因,这两个迭代器不共享共同的祖先,迫使编写如下代码:

  if (recursive_) {
    path = recursive_iterator_->path();
    recursive_iterator_++;
  } else {
    path = plain_iterator_->path();
    plain_iterator_++;
  }

我不敢相信这是它应该如何工作的。我最初还假设有一些选项可以关闭 recursive_directory_iterator 的递归,但在 std::filesystem::directory_options 之间似乎没有任何选项。

该值在编译时未知。我认为应该可以使用闭包之类的东西,甚至可以使用带有虚拟方法的子类,但看起来有点矫枉过正。

我应该根据需要简单地使用两个迭代器之间的条件切换,还是有更好的方法?

标签: c++c++17

解决方案


实现相同的接口

他们是这样。它们都是InputIterator即取消引用const std::filesystem::directory_entry&.

C++ 默认避免virtual

您可以使用boost::any_range类型擦除递归性。

template <typename... Args>
auto make_directory_range(bool recursive, Args... args) {
    return recursive
        ? boost::make_iterator_range(fs::recursive_directory_iterator(args...), fs::recursive_directory_iterator()) | boost::adaptors::type_erased()
        : boost::make_iterator_range(fs::directory_iterator(args...), fs::directory_iterator());
}

using iterator_t = decltype(make_directory_range(true).begin());

auto range = make_directory_range(recursive_, args...);
iterator_t iterator = range.begin();
iterator_t end = range.end();

推荐阅读