Skip to content

Commit 21961bb

Browse files
misccoAdamBuciorCaseyCarterStephanTLavavej
authored
Implement P2210R2 Superior String Splitting (#2042)
Co-authored-by: Adam Bucior <[email protected]> Co-authored-by: Casey Carter <[email protected]> Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 671daf4 commit 21961bb

File tree

9 files changed

+849
-264
lines changed

9 files changed

+849
-264
lines changed

stl/inc/algorithm

Lines changed: 0 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,156 +1962,6 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(
19621962
return _Search(_First, _Last).first;
19631963
}
19641964

1965-
#ifdef __cpp_lib_concepts
1966-
namespace ranges {
1967-
// clang-format off
1968-
template <class _It1, class _It2, class _Se2, class _Pr, class _Pj1, class _Pj2>
1969-
concept _Equal_rev_pred_can_memcmp = is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>
1970-
&& sized_sentinel_for<_Se2, _It2> && _Equal_memcmp_is_safe<_It1, _It2, _Pr>;
1971-
1972-
template <input_iterator _It1, input_iterator _It2, sentinel_for<_It2> _Se2, class _Pr, class _Pj1, class _Pj2>
1973-
requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>
1974-
_NODISCARD constexpr pair<bool, _It1> _Equal_rev_pred(
1975-
_It1 _First1, _It2 _First2, const _Se2 _Last2, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
1976-
// Returns {true, _First1 + (_Last2 - _First2)} if [_First1, ...) equals [_First2, _Last2), and {false, {}}
1977-
// otherwise.
1978-
constexpr bool _Optimize = _Equal_rev_pred_can_memcmp<_It1, _It2, _Se2, _Pr, _Pj1, _Pj2>;
1979-
if constexpr (_Optimize) {
1980-
if (!_STD is_constant_evaluated()) {
1981-
bool _Ans;
1982-
if constexpr (same_as<_It2, _Se2>) {
1983-
_Ans = _Memcmp_ranges(_First2, _Last2, _First1) == 0;
1984-
} else {
1985-
_Ans = _Memcmp_count(_First1, _First2, static_cast<size_t>(_Last2 - _First2)) == 0;
1986-
}
1987-
1988-
if (_Ans) {
1989-
_First1 += (_Last2 - _First2);
1990-
return {true, _STD move(_First1)};
1991-
} else {
1992-
return {false, _It1{}};
1993-
}
1994-
}
1995-
}
1996-
1997-
for (; _First2 != _Last2; ++_First1, (void) ++_First2) {
1998-
if (!_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_First2))) {
1999-
return {false, _It1{}};
2000-
}
2001-
}
2002-
2003-
return {true, _STD move(_First1)};
2004-
}
2005-
// clang-format on
2006-
2007-
class _Search_fn : private _Not_quite_object {
2008-
public:
2009-
using _Not_quite_object::_Not_quite_object;
2010-
2011-
// clang-format off
2012-
template <forward_iterator _It1, sentinel_for<_It1> _Se1, forward_iterator _It2, sentinel_for<_It2> _Se2,
2013-
class _Pr = ranges::equal_to, class _Pj1 = identity, class _Pj2 = identity>
2014-
requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>
2015-
_NODISCARD constexpr subrange<_It1> operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2,
2016-
_Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
2017-
_Adl_verify_range(_First1, _Last1);
2018-
_Adl_verify_range(_First2, _Last2);
2019-
auto _UFirst1 = _Get_unwrapped(_STD move(_First1));
2020-
auto _ULast1 = _Get_unwrapped(_STD move(_Last1));
2021-
auto _UFirst2 = _Get_unwrapped(_STD move(_First2));
2022-
auto _ULast2 = _Get_unwrapped(_STD move(_Last2));
2023-
2024-
if constexpr (sized_sentinel_for<_Se1, _It1> && sized_sentinel_for<_Se2, _It2>) {
2025-
const auto _Count1 = _ULast1 - _UFirst1;
2026-
const auto _Count2 = _ULast2 - _UFirst2;
2027-
auto _UResult =
2028-
_Search_sized(_STD move(_UFirst1), _STD move(_ULast1), _Count1, _STD move(_UFirst2),
2029-
_STD move(_ULast2), _Count2, _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
2030-
return _Rewrap_subrange<subrange<_It1>>(_First1, _STD move(_UResult));
2031-
} else {
2032-
auto _UResult = _Search_unsized(_STD move(_UFirst1), _STD move(_ULast1), _STD move(_UFirst2),
2033-
_STD move(_ULast2), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
2034-
return _Rewrap_subrange<subrange<_It1>>(_First1, _STD move(_UResult));
2035-
}
2036-
}
2037-
2038-
template <forward_range _Rng1, forward_range _Rng2, class _Pr = ranges::equal_to, class _Pj1 = identity,
2039-
class _Pj2 = identity>
2040-
requires indirectly_comparable<iterator_t<_Rng1>, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2>
2041-
_NODISCARD constexpr borrowed_subrange_t<_Rng1> operator()(
2042-
_Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
2043-
if constexpr (sized_range<_Rng1> && sized_range<_Rng2>) {
2044-
const auto _Count1 = _RANGES distance(_Range1);
2045-
const auto _Count2 = _RANGES distance(_Range2);
2046-
auto _UResult = _Search_sized(_Ubegin(_Range1), _Uend(_Range1), _Count1,
2047-
_Ubegin(_Range2), _Uend(_Range2), _Count2,
2048-
_Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
2049-
return _Rewrap_subrange<borrowed_subrange_t<_Rng1>>(_Range1, _STD move(_UResult));
2050-
} else {
2051-
auto _UResult = _Search_unsized(_Ubegin(_Range1), _Uend(_Range1),
2052-
_Ubegin(_Range2), _Uend(_Range2),
2053-
_Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
2054-
return _Rewrap_subrange<borrowed_subrange_t<_Rng1>>(_Range1, _STD move(_UResult));
2055-
}
2056-
}
2057-
// clang-format on
2058-
2059-
private:
2060-
template <class _It1, class _Se1, class _It2, class _Se2, class _Pr, class _Pj1, class _Pj2>
2061-
_NODISCARD static constexpr subrange<_It1> _Search_sized(_It1 _First1, const _Se1 _Last1,
2062-
iter_difference_t<_It1> _Count1, _It2 _First2, const _Se2 _Last2, const iter_difference_t<_It2> _Count2,
2063-
_Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
2064-
_STL_INTERNAL_STATIC_ASSERT(forward_iterator<_It1>);
2065-
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se1, _It1>);
2066-
_STL_INTERNAL_STATIC_ASSERT(forward_iterator<_It2>);
2067-
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>);
2068-
_STL_INTERNAL_STATIC_ASSERT(indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>);
2069-
_STL_INTERNAL_CHECK(_RANGES distance(_First1, _Last1) == _Count1);
2070-
_STL_INTERNAL_CHECK(_RANGES distance(_First2, _Last2) == _Count2);
2071-
2072-
for (; _Count1 >= _Count2; ++_First1, (void) --_Count1) {
2073-
auto [_Match, _Mid1] = _RANGES _Equal_rev_pred(_First1, _First2, _Last2, _Pred, _Proj1, _Proj2);
2074-
if (_Match) {
2075-
return {_STD move(_First1), _STD move(_Mid1)};
2076-
}
2077-
}
2078-
2079-
_First1 = _Find_last_iterator(_First1, _Last1, _Count1);
2080-
return {_First1, _First1};
2081-
}
2082-
2083-
template <class _It1, class _Se1, class _It2, class _Se2, class _Pr, class _Pj1, class _Pj2>
2084-
_NODISCARD static constexpr subrange<_It1> _Search_unsized(
2085-
_It1 _First1, const _Se1 _Last1, _It2 _First2, const _Se2 _Last2, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
2086-
_STL_INTERNAL_STATIC_ASSERT(forward_iterator<_It1>);
2087-
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se1, _It1>);
2088-
_STL_INTERNAL_STATIC_ASSERT(forward_iterator<_It2>);
2089-
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>);
2090-
_STL_INTERNAL_STATIC_ASSERT(indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>);
2091-
2092-
for (;; ++_First1) {
2093-
auto _Mid1 = _First1;
2094-
for (auto _Mid2 = _First2;; ++_Mid1, (void) ++_Mid2) {
2095-
if (_Mid2 == _Last2) { // match
2096-
return {_STD move(_First1), _STD move(_Mid1)};
2097-
}
2098-
2099-
if (_Mid1 == _Last1) { // not enough haystack left to find a match
2100-
return {_Mid1, _Mid1};
2101-
}
2102-
2103-
if (!_STD invoke(_Pred, _STD invoke(_Proj1, *_Mid1), _STD invoke(_Proj2, *_Mid2))) { // mismatch
2104-
break;
2105-
}
2106-
}
2107-
}
2108-
}
2109-
};
2110-
2111-
inline constexpr _Search_fn search{_Not_quite_object::_Construct_tag{}};
2112-
} // namespace ranges
2113-
#endif // __cpp_lib_concepts
2114-
21151965
template <class _FwdIt, class _Diff, class _Ty, class _Pr>
21161966
_NODISCARD _CONSTEXPR20 _FwdIt search_n(
21171967
const _FwdIt _First, _FwdIt _Last, const _Diff _Count_raw, const _Ty& _Val, _Pr _Pred) {

0 commit comments

Comments
 (0)