А то для используемого мною (Linaro GCC 7.5-2019.12) 7.5.0 std::experimental::filesystem::directory_iterator
вызов std::next(dirIt); меняет dirIt.
Это фича или баг?
И каждый день — без права на ошибку...
Re: std::next для std::filesystem::directory_iterator
Это различие между InputIterator и ForwardIterator: первый принципиально однопроходный, второй допускает несколько проходов.
BFE>вывод в строчках 1 и 2 должен совпадать?
Не должен. И работать тоже не обязан.
Так как directory_iterator — это input iterator. Инкремент может инвалидировать предыдущие ссылки, освобождать ресурсы, и т.п.
Re[2]: std::next для std::filesystem::directory_iterator
Здравствуйте, watchmaker, Вы писали:
W>Так как directory_iterator — это input iterator. Инкремент может инвалидировать предыдущие ссылки, освобождать ресурсы, и т.п.
Зачем он input iterator? Трудно, что ли, было сделать ForwardIterator?
И каждый день — без права на ошибку...
Re: std::next для std::filesystem::directory_iterator
Сложный вопрос. По идее, если считать что в std::next итератор передаётся по значению, то не должен. Но видимо у std::filesystem::directory_iterator хитрая реализация, допускающая что копия итератора (переданная в next и инкрементированная) так же владеет данными итератора, и поэтому в реальности вывод не совпадает
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, watchmaker, Вы писали:
W>>Так как directory_iterator — это input iterator. Инкремент может инвалидировать предыдущие ссылки, освобождать ресурсы, и т.п. BFE>Зачем он input iterator? Трудно, что ли, было сделать ForwardIterator?
BFE>>вывод в строчках 1 и 2 должен совпадать?
AD>Сложный вопрос. По идее, если считать что в std::next итератор передаётся по значению, то не должен. Но видимо у std::filesystem::directory_iterator хитрая реализация, допускающая что копия итератора (переданная в next и инкрементированная) так же владеет данными итератора, и поэтому в реальности вывод не совпадает
directory_iterator& operator++();
directory_iterator& increment( std::error_code& ec );
(since C++17)
Advances the iterator to the next entry. Invalidates all copies of the previous value of *this.
Повезло что оно вообще работает, а могло бы на второй строке посыпаться с диагностикой типа "не могу разыменовать невалидный итератор"
Re[2]: std::next для std::filesystem::directory_iterator
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, vopl, Вы писали:
V>>
V>>Advances the iterator to the next entry. Invalidates all copies of the previous value of *this.
V>>Повезло что оно вообще работает, а могло бы на второй строке посыпаться с диагностикой типа "не могу разыменовать невалидный итератор"
AD>Не совсем ясно из описания, обращение к dirIt после std::next — это UB или не UB?
Обращение к dirIt после std::next это нарушение условий его использования, инвалидные итераторы нельзя разыменовывать (тут табличка https://en.cppreference.com/w/cpp/named_req/InputIterator, она же в стандарте [tab:inputiterator]). UB или не UB — как по мне так уже и не важно, потому что нарушены условия, уже все плохо.
Re[3]: std::next для std::filesystem::directory_iterator
Здравствуйте, vopl, Вы писали:
V>Повезло что оно вообще работает, а могло бы на второй строке посыпаться с диагностикой типа "не могу разыменовать невалидный итератор"
Наоборот же.
Везёт — это когда в случае допущенной ошибки получаешь диагностику. И вдвойне везёт, если это происходит рядом с местом ошибки (на этой самой "второй строке").
А когда код порождает UB, которое не ловится стандартным санитайзером (ubsan) и при этом проявляется не в виде падения, а выдаёт что-то похожее на нормальный ответ, то это явно хуже вариант, так как требует долгой отладки. Хуже этого только плавающие баги, которые не получается надёжно воспроизводить