From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1888) id CFC633857417; Sun, 20 Jun 2021 16:51:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CFC633857417 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Patrick Palka To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r12-1663] libstdc++: Implement P2210 changes to split_view resolving LWG 3478 X-Act-Checkin: gcc X-Git-Author: Patrick Palka X-Git-Refname: refs/heads/master X-Git-Oldrev: 85a594f7dc8ea5c765e136f162debb668139ebd4 X-Git-Newrev: 3f631671f17f44c611c70c59ef3338eab2ab67b3 Message-Id: <20210620165104.CFC633857417@sourceware.org> Date: Sun, 20 Jun 2021 16:51:04 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Jun 2021 16:51:04 -0000 https://gcc.gnu.org/g:3f631671f17f44c611c70c59ef3338eab2ab67b3 commit r12-1663-g3f631671f17f44c611c70c59ef3338eab2ab67b3 Author: Patrick Palka Date: Sun Jun 20 12:38:43 2021 -0400 libstdc++: Implement P2210 changes to split_view resolving LWG 3478 This implements the part of P2210R2 "Superior String Splitting" that resolves LWG 3478. libstdc++-v3/ChangeLog: * include/std/ranges (split_view::_OuterIter::__at_end): Check _M_trailing_empty. (split_view::_OuterIter::_M_trailing_empty): Define this data member. (split_view::_OuterIter::operator++): Set _M_trailing_empty appropriately. (split_view::_OuterIter::operator==): Compare _M_trailing_empty. * testsuite/std/ranges/adaptors/100479.cc (test03): Expect two split parts instead of one. * testsuite/std/ranges/adaptors/split.cc (test11): New test. Diff: --- libstdc++-v3/include/std/ranges | 21 +++++++++++++++++---- .../testsuite/std/ranges/adaptors/100479.cc | 6 +++--- libstdc++-v3/testsuite/std/ranges/adaptors/split.cc | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 7cb8b2da506..5eba6913517 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -2879,7 +2879,7 @@ namespace views::__adaptor constexpr bool __at_end() const - { return __current() == ranges::end(_M_parent->_M_base); } + { return __current() == ranges::end(_M_parent->_M_base) && !_M_trailing_empty; } // [range.split.outer] p1 // Many of the following specifications refer to the notional member @@ -2909,6 +2909,7 @@ namespace views::__adaptor [[no_unique_address]] __detail::__maybe_present_t, iterator_t<_Base>> _M_current; + bool _M_trailing_empty = false; public: using iterator_concept = conditional_t, @@ -2971,7 +2972,10 @@ namespace views::__adaptor // 3505. split_view::outer-iterator::operator++ misspecified const auto __end = ranges::end(_M_parent->_M_base); if (__current() == __end) - return *this; + { + _M_trailing_empty = false; + return *this; + } const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern}; if (__pbegin == __pend) ++__current(); @@ -2980,7 +2984,11 @@ namespace views::__adaptor __current() = ranges::find(std::move(__current()), __end, *__pbegin); if (__current() != __end) - ++__current(); + { + ++__current(); + if (__current() == __end) + _M_trailing_empty = true; + } } else do @@ -2990,6 +2998,8 @@ namespace views::__adaptor if (__p == __pend) { __current() = __b; + if (__current() == __end) + _M_trailing_empty = true; break; } } while (++__current() != __end); @@ -3012,7 +3022,10 @@ namespace views::__adaptor friend constexpr bool operator==(const _OuterIter& __x, const _OuterIter& __y) requires forward_range<_Base> - { return __x._M_current == __y._M_current; } + { + return __x._M_current == __y._M_current + && __x._M_trailing_empty == __y._M_trailing_empty; + } friend constexpr bool operator==(const _OuterIter& __x, default_sentinel_t) diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc index ba10b7baf3f..b16679075c6 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc @@ -95,11 +95,11 @@ test03() | views::drop_while([](auto) { return false; }) | views::filter([](auto) { return true; }); static_assert(ranges::forward_range); - VERIFY( ranges::next(v.begin()) == v.end() ); + VERIFY( ranges::distance(v) == 2 ); auto w = v; - VERIFY( ranges::next(w.begin()) == w.end() ); + VERIFY( ranges::distance(v) == 2 ); auto z = std::move(w); - VERIFY( ranges::next(z.begin()) == z.end() ); + VERIFY( ranges::distance(v) == 2 ); return true; } diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc index 9d2cfa8632a..215856801ba 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc @@ -193,6 +193,25 @@ test10() VERIFY( ranges::equal(v, (std::string_view[]){"x", "x"}) ); } +void +test11() +{ + // LWG 3478 + auto v = views::split("text"sv, "text"sv); + auto i = v.begin(); + VERIFY( ranges::empty(*i++) ); + VERIFY( ranges::empty(*i++) ); + VERIFY( i == v.end() ); + + static_assert(ranges::distance(views::split(" text "sv, ' ')) == 3); + static_assert(ranges::distance(views::split(" t e x t "sv, ' ')) == 6); + static_assert(ranges::distance(views::split(" text "sv, " "sv)) == 3); + static_assert(ranges::distance(views::split(" text "sv, " "sv)) == 4); + static_assert(ranges::distance(views::split(" text "sv, " "sv)) == 4); + static_assert(ranges::distance(views::split("t"sv, 't')) == 2); + static_assert(ranges::distance(views::split("text"sv, ""sv)) == 4); +} + int main() { @@ -206,4 +225,5 @@ main() test08(); test09(); test10(); + test11(); }