From b5242b284549cc7994a8dc073f9e1479ee0ae915 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Thu, 8 Apr 2021 16:45:27 -0400 Subject: [PATCH] libstdc++: Fix split_view::_OuterIter::operator++ [LWG 3505] libstdc++-v3/ChangeLog: * include/std/ranges (__detail::find): Define. (split_view::_OuterIter::operator++): Apply proposed resolution of LWG 3505. * testsuite/std/ranges/adaptors/split.cc (test10): New test. --- libstdc++-v3/include/std/ranges | 28 ++++++++++++++++--- .../testsuite/std/ranges/adaptors/split.cc | 12 ++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 9077271e4e6..baec8c0efef 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -982,6 +982,16 @@ namespace views::__adaptor // having to include that entire header. namespace __detail { + template + constexpr _Iter + find(_Iter __first, _Sent __last, const _Tp& __value) + { + while (__first != __last + && !(bool)(*__first == __value)) + ++__first; + return __first; + } + template constexpr _Iter find_if(_Iter __first, _Sent __last, _Pred __pred) @@ -2656,21 +2666,31 @@ namespace views::__adaptor constexpr _OuterIter& operator++() { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3505. split_view::outer-iterator::operator++ misspecified const auto __end = ranges::end(_M_parent->_M_base); if (__current() == __end) return *this; const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern}; if (__pbegin == __pend) ++__current(); + else if constexpr (__detail::__tiny_range<_Pattern>) + { + __current() = __detail::find(std::move(__current()), __end, + *__pbegin); + if (__current() != __end) + ++__current(); + } else do { auto [__b, __p] - = __detail::mismatch(std::move(__current()), __end, - __pbegin, __pend); - __current() = std::move(__b); + = __detail::mismatch(__current(), __end, __pbegin, __pend); if (__p == __pend) - break; + { + __current() = __b; + break; + } } while (++__current() != __end); return *this; } diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc index b9fb3728708..9d2cfa8632a 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc @@ -182,6 +182,17 @@ test09() static_assert(requires { adapt2(s); }); } +void +test10() +{ + // LWG 3505 + auto to_string = [] (auto r) { + return std::string(r.begin(), ranges::next(r.begin(), r.end())); + }; + auto v = "xxyx"sv | views::split("xy"sv) | views::transform(to_string); + VERIFY( ranges::equal(v, (std::string_view[]){"x", "x"}) ); +} + int main() { @@ -194,4 +205,5 @@ main() test07(); test08(); test09(); + test10(); }