@@ -1962,156 +1962,6 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(
1962
1962
return _Search(_First, _Last).first;
1963
1963
}
1964
1964
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
-
2115
1965
template <class _FwdIt, class _Diff, class _Ty, class _Pr>
2116
1966
_NODISCARD _CONSTEXPR20 _FwdIt search_n(
2117
1967
const _FwdIt _First, _FwdIt _Last, const _Diff _Count_raw, const _Ty& _Val, _Pr _Pred) {
0 commit comments