I need to find all regular files in a directory, and would like to use the C++20 ranges (not Eric Niebler's range-v3) library. I came up with the following code:
namespace fs = std::filesystem;
std::vector<fs::directory_entry> entries{ fs::directory_iterator("D:\\Path"), fs::directory_iterator() };
std::vector<fs::path> paths;
std::ranges::copy(entries |
std::views::filter([](const fs::directory_entry& entry) { return entry.is_regular_file(); }) |
std::views::transform([](const fs::directory_entry& entry) { return entry.path(); }),
std::back_inserter(paths));
This works, but I'm uncomfortable with the additional boilerplate of using lambdas; I'm used to the Java 8 streams library, and I don't see why I can't just use member functions directly. This was my first attempt at refactoring:
std::ranges::copy(entries |
std::views::filter(fs::directory_entry::is_regular_file) |
std::views::transform(fs::directory_entry::path),
std::back_inserter(paths));
This resulted in compiler errors:
error C3867: 'std::filesystem::directory_entry::is_regular_file': non-standard syntax; use '&' to create a pointer to member
error C3889: call to object of class type 'std::ranges::views::_Filter_fn': no matching call operator found
...
So I tried this:
std::ranges::copy(entries |
std::views::filter(&fs::directory_entry::is_regular_file) |
std::views::transform(&fs::directory_entry::path),
std::back_inserter(paths));
This fixed the first error, but not the second:
error C3889: call to object of class type 'std::ranges::views::_Filter_fn': no matching call operator found
...
So I found Using member variable as predicate, which looked promising, so I tried:
std::ranges::copy(entries |
std::views::filter(std::mem_fn(&fs::directory_entry::is_regular_file)) |
std::views::transform(std::mem_fn(&fs::directory_entry::path)),
std::back_inserter(paths));
This resulted in new compiler errors:
error C2672: 'std::mem_fn': no matching overloaded function found
...
Note, std::bind
doesn't appear to work either. Any help would be appreciated, thanks!