I was using the experimental std::filesystem
implementation in gcc 6.3.1, and ran into some very unexpected behavior with regard to std::experimental::filesystem::directory_iterator
and std::distance
. Specifically, after a call to std::distance
, the original iterator appeared to have been modified.
After a bunch of fruitless debugging trying to find a logical error in my code, I started digging around in the implementation of directory_iterator
, and finally found that the iterator uses std::shared_ptr
internally, has a default copy-constructor, and I assume that operator++
must be directly incrementing the managed pointer.
The following code reproduces the issue:
#include <iostream>
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
int main() {
auto it = fs::directory_iterator("/etc");
std::cout << *it << std::endl;
std::distance(it, fs::directory_iterator{});
std::cout << *it << std::endl;
}
As this kind of implementation yields wildly counter-intuitive results whenever passing to a function that expects iterators with traditional value-semantics (all of the STL algorithms, as far as I know), I have a hard time believing this is intended behavior, but am hesitant to call a bug.
Obviously, this API was experimental at the time of release, but I was thinking it was intended to be a faithful implementation of the filesystem TS. I don't have access to a compiler with full C++17
support, so I had been hoping to use this in the intervening time.
Is this intended behavior, and should I expect directory_iterator
to work this way in future releases? For the time being I guess I can use boost::filesystem
.
Thanks!
directory_iterators are defined to be InputIterators and therefore can only be used once. There is no const addition operator so you have to use the increment operator which modifies the iterator.