diff options
author | Patrick Palka <ppalka@redhat.com> | 2021-06-20 12:38:43 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2021-06-20 12:38:43 -0400 |
commit | 3f631671f17f44c611c70c59ef3338eab2ab67b3 (patch) | |
tree | ae600158d09966bc10d2d7c0d0acadea23fc12c9 /libstdc++-v3 | |
parent | 85a594f7dc8ea5c765e136f162debb668139ebd4 (diff) | |
download | gcc-3f631671f17f44c611c70c59ef3338eab2ab67b3.zip gcc-3f631671f17f44c611c70c59ef3338eab2ab67b3.tar.gz gcc-3f631671f17f44c611c70c59ef3338eab2ab67b3.tar.bz2 |
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.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/include/std/ranges | 21 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc | 6 | ||||
-rw-r--r-- | 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 7cb8b2d..5eba691 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<forward_range<_Vp>, iterator_t<_Base>> _M_current; + bool _M_trailing_empty = false; public: using iterator_concept = conditional_t<forward_range<_Base>, @@ -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 ba10b7b..b166790 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<decltype(v)>); - 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 9d2cfa8..2158568 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(); } |