C++ Logo

std-proposals

Advanced search

Re: [std-proposals] filesystem::path::iterator should be bidirectional_iterator even if it's not Cpp17BidirectionalIterator

From: Ell <ell.ell.se_at_[hidden]>
Date: Tue, 03 Feb 2026 22:40:12 +0000
On Tuesday, February 3rd, 2026 at 11:18 PM, Arthur O'Dwyer via Std-Proposals <std-proposals_at_[hidden]> wrote:

> On Thu, Jan 29, 2026 at 8:48 PM 梁家铭 via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> > Hi,
> >
> > Recently I find that `filesystem::path::iterator` is not bidirectional iterator, as specified in Issue 2674: Bidirectional iterator requirement on path::iterator is very expensive. It fulfills all requirements of Cpp17BidirectionalIterator except that there is no requirement that two equal iterators be bound to the same object (See [fs.class.path]). The reason is that it allows the iterator to cache filename component (as libc++ and MS-STL do) instead of storing a container of components in filesystem::path (as libstdc++ does, unfortunately). However, it also degrades path::iterator from Cpp17BidirectionalIterator to Cpp17InputIterator (well only libstdc++ can and indeed mark it with bidirectional_iterator_tag). Such degradation is also counter-intuitive and makes many components in `<algorithm>` inapplicable (e.g. libc++ issue: https://github.com/llvm/llvm-project/issues/55683).
> >
> > However, such simplification is very like `std::views::split`, which makes it fulfill bidirectional_iterator since C++20 if we examine all concepts one by one except the iterator tag. And C++20 allows us to define `iterator_concept` instead of examining `iterator_tag`. So I think we should make a fix DR (bold means wording change):
> >
> > A path::iterator is a constant iterator meeting all the requirements of a Cpp17BidirectionalIterator except that, for dereferenceable iterators a and b of type path::iterator with a == b, there is no requirement that *a and *b are bound to the same object.
> > Its value_type is path. Therefore, it should fulfill concept
> > bidirectional_iterator.
> >
> > And implementations can utilize `iterator_concept` to support it.
>
>
> This sounds to me like a reasonable topic for a paper. I mean, this seems 100% like LEWG design territory — although I admit I'm confused by the existence of LWG 2674 and the implementation divergence between libc++/libstdc++ and Microsoft.
>
> I haven't investigated this area myself, so I don't have a concrete suggestion for wording. But the stuff you wrote in green above is not good wording. Don't say something "should" do something; just show the actual diff you're proposing. Find the words in the Standard that are currently as-they-should-not-be, and show how to replace them with something better.
> You say path::iterator should [sic] "fulfill" concept `bidirectional_iterator`. But that's not a thing. We can say that path::iterator satisfies `bidirectional_iterator`; this is already true on libc++ and libstdc++, but false on MS STL. However, I'm confused by your phrasing — are you saying you want path::iterator to satisfy `bidirectional_iterator` without modeling `bidirectional_iterator`? Doesn't that make lots of usages IFNDR, technically? Obviously such IFNDR-ness would be harmless in practice; but how could WG21 possibly standardize anything along those lines with a straight face — "we provide a library type that satisfies a library concept but doesn't model it"? That way lies madness, it seems to me.
> Maybe I'm just missing something basic; again, I haven't looked deeply at this at all. But you could help by providing the exact wording you think ought to change, and how to change it.
>


C++20 forward iterators still require returned lvalues to outlive the
iterator
(https://eel.is/c++draft/iterator.concepts#iterator.concept.forward-3),
so they can't both cache the result and return it by reference. libc++
returns the cached path by value, so it can and does declare
iterator_concept as bidirectional. Not sure when it was added, OP might
want to try a newer version. I'm also not sure if dereferencing the
iterator is strictly speaking O(1), but the complexity requirements for
iterators don't make much sense anyway.

MS STL returns the cached path by reference so it can't be a
bidirectional iterator, and pretending to be one would definitely not be
harmless (think about reverse_iterator<path_iterator>).

Received on 2026-02-03 22:40:18