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.
This commit is contained in:
parent
85a594f7dc
commit
3f631671f1
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user