diff options
author | Patrick Palka <ppalka@redhat.com> | 2021-04-08 16:45:27 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2021-04-08 16:45:27 -0400 |
commit | b5242b284549cc7994a8dc073f9e1479ee0ae915 (patch) | |
tree | d0075049c6d63833143b7f1d5d5acf7900177ad9 | |
parent | c1ce418af29bc1796bfe82a5aa97639eccc30cb7 (diff) | |
download | gcc-b5242b284549cc7994a8dc073f9e1479ee0ae915.zip gcc-b5242b284549cc7994a8dc073f9e1479ee0ae915.tar.gz gcc-b5242b284549cc7994a8dc073f9e1479ee0ae915.tar.bz2 |
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.
-rw-r--r-- | libstdc++-v3/include/std/ranges | 28 | ||||
-rw-r--r-- | libstdc++-v3/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 9077271..baec8c0 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<typename _Iter, typename _Sent, typename _Tp> + constexpr _Iter + find(_Iter __first, _Sent __last, const _Tp& __value) + { + while (__first != __last + && !(bool)(*__first == __value)) + ++__first; + return __first; + } + template<typename _Iter, typename _Sent, typename _Pred> 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 b9fb372..9d2cfa8 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(); } |