Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic way to use fs::recursive_directory_iterator() and fs::directory_iterator()

Tags:

c++

c++17

I need to iterate over folder either recursively or not (given the boolean parameter). I have discovered there is fs::recursive_directory_iterator() and also fs::directory_iterator(). In Java, I would expect them to implement the same interface or share the common ancestor so that I could substitute the needed one. But for some reason the two iterators do not share the common ancestor, forcing the to write the code like:

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

I cannot believe this is how it is supposed to work. I also initially assumed there are some options to turn off recursion for recursive_directory_iterator but seems no any between std::filesystem::directory_options.

The value is not known at the compile time. I think it should be possible to use something like a closure or even subclass with virtual method but looks a bit like overkill.

Should I simply use conditionals switching between the two iterators as needed, or there are better approaches?

like image 267
Audrius Meškauskas Avatar asked Nov 04 '25 05:11

Audrius Meškauskas


1 Answers

implement the same interface

They do. They are both InputIterators, that dereference to const std::filesystem::directory_entry&.

C++ avoids virtual by default.

You can use boost::any_range to type erase the recursiveness.

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();
like image 146
Caleth Avatar answered Nov 06 '25 19:11

Caleth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!