https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100479
Bug ID: 100479
Summary: range adaptors handle cached iterators incorrectly
Product: gcc
Version: 12.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: rs2740 at gmail dot com
Target Milestone: ---
template<forward_range _Range>
struct _CachedPosition<_Range>
{
private:
iterator_t<_Range> _M_iter{};
public:
constexpr bool
_M_has_value() const
{ return _M_iter != iterator_t<_Range>{}; }
constexpr iterator_t<_Range>
_M_get(const _Range&) const
{
__glibcxx_assert(_M_has_value());
return _M_iter;
}
constexpr void
_M_set(const _Range&, const iterator_t<_Range>& __it)
{
__glibcxx_assert(!_M_has_value());
_M_iter = __it;
}
};
- The domain of == for forward iterators is limited to iterators over the same
underlying sequence. While value-initialized forward iterators of the same type
may be compared against each other, comparing them against iterators into other
ranges is not required to be well-defined, so it cannot be used as a sentinel
value.
- The cache cannot be allowed to propagate when the view containing it is
copied/moved, and has to be invalidated when the view containing it is moved.
Any cached iterator points to the original underlying view, and not the new
one; also, moving from a view can change its value (if it is well-defined to
use the moved-from view), so the cache is no longer valid. (Handling this case
correctly was actually the original use case for non-propagating-cache in
range-v3.)