From d85f6047e6f3891b900f5697c9eff2c99dde8776 Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Sun, 24 Jul 2022 15:07:56 +0100 Subject: [PATCH 1/8] Implement P2302R3 ranges::contains --- stl/inc/algorithm | 46 +++++++ stl/inc/yvals_core.h | 2 + .../tests/P2302R3_ranges_alg_contains/env.lst | 4 + .../P2302R3_ranges_alg_contains/test.cpp | 64 ++++++++++ .../env.lst | 4 + .../test.cpp | 112 ++++++++++++++++++ .../test.compile.pass.cpp | 14 +++ 7 files changed, 246 insertions(+) create mode 100644 tests/std/tests/P2302R3_ranges_alg_contains/env.lst create mode 100644 tests/std/tests/P2302R3_ranges_alg_contains/test.cpp create mode 100644 tests/std/tests/P2302R3_ranges_alg_contains_subrange/env.lst create mode 100644 tests/std/tests/P2302R3_ranges_alg_contains_subrange/test.cpp diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 49158096e7..e1f8d8ac9f 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1364,6 +1364,52 @@ namespace ranges { inline constexpr _None_of_fn none_of{_Not_quite_object::_Construct_tag{}}; + class _Contains_fn : private _Not_quite_object { + public: + using _Not_quite_object::_Not_quite_object; + + template _Se, class _Ty, class _Pj = identity> + requires indirect_binary_predicate < ranges::equal_to, projected<_It, _Pj>, + const _Ty* > // + _NODISCARD constexpr bool operator()(_It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) const { + return _RANGES find(_STD move(_First), _Last, _Val, _Pass_fn(_Proj)) != _Last; + } + template + requires indirect_binary_predicate < ranges::equal_to, projected, _Pj>, + const _Ty* > // + _NODISCARD constexpr bool operator()(_Rng&& _Range, const _Ty& _Val, _Pj _Proj = {}) const { + return (*this)(_RANGES begin(_Range), _RANGES end(_Range), _Val, _Pass_fn(_Proj)); + } + }; + + inline constexpr _Contains_fn contains{_Not_quite_object::_Construct_tag{}}; + + class _Contains_subrange_fn : private _Not_quite_object { + public: + using _Not_quite_object::_Not_quite_object; + + template _Se1, forward_iterator _It2, sentinel_for<_It2> _Se2, + class _Pr = ranges::equal_to, class _Pj1 = identity, class _Pj2 = identity> + requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2> // + _NODISCARD constexpr bool operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred = {}, + _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { + return _First2 == _Last2 + || !ranges::search( + _First1, _Last1, _First2, _Last2, _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)) + .empty(); + } + template + requires indirectly_comparable, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2> // + _NODISCARD constexpr bool operator()( + _Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { + return (*this)(_RANGES begin(_Range1), _RANGES end(_Range1), _RANGES begin(_Range2), _RANGES end(_Range2), + _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)); + } + }; + + inline constexpr _Contains_subrange_fn contains_subrange{_Not_quite_object::_Construct_tag{}}; + template using copy_n_result = in_out_result<_In, _Out>; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index b9064e29e8..f1aaf1083c 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -309,6 +309,7 @@ // P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr // P2186R2 Removing Garbage Collection Support // P2273R3 constexpr unique_ptr +// P2302R3 ranges::contains // P2321R2 zip // (changes to pair, tuple, and vector::reference only) // P2440R1 ranges::iota, ranges::shift_left, ranges::shift_right @@ -1462,6 +1463,7 @@ #define __cpp_lib_out_ptr 202106L #define __cpp_lib_ranges_chunk 202202L #define __cpp_lib_ranges_chunk_by 202202L +#define __cpp_lib_ranges_contains 202207L #define __cpp_lib_ranges_iota 202202L #define __cpp_lib_ranges_join_with 202202L #define __cpp_lib_ranges_slide 202202L diff --git a/tests/std/tests/P2302R3_ranges_alg_contains/env.lst b/tests/std/tests/P2302R3_ranges_alg_contains/env.lst new file mode 100644 index 0000000000..18e2d7c71e --- /dev/null +++ b/tests/std/tests/P2302R3_ranges_alg_contains/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P2302R3_ranges_alg_contains/test.cpp b/tests/std/tests/P2302R3_ranges_alg_contains/test.cpp new file mode 100644 index 0000000000..fcfcda10e5 --- /dev/null +++ b/tests/std/tests/P2302R3_ranges_alg_contains/test.cpp @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +#include + +using namespace std; + +struct instantiator { + static constexpr pair haystack[3] = {{0, 42}, {2, 42}, {4, 42}}; + + template + static constexpr void call() { + using ranges::contains, ranges::begin, ranges::end; + + for (const auto& [value, _] : haystack) { + { // Validate range overload [found case] + const same_as auto result = contains(In{haystack}, value, get_first); + assert(result); + } + { // Validate iterator + sentinel overload [found case] + const In wrapped{haystack}; + const same_as auto result = contains(begin(wrapped), end(wrapped), value, get_first); + assert(result); + } + } + { + // Validate range overload [not found case] + const same_as auto result = contains(In{haystack}, 42, get_first); + assert(!result); + } + { + // Validate iterator + sentinel overload [not found case] + const In wrapped{haystack}; + const same_as auto result = contains(begin(wrapped), end(wrapped), 42, get_first); + assert(!result); + } + { // Validate memchr case + const char arr[5]{4, 8, 1, -15, 125}; + + // found case + same_as auto result = contains(arr, 1); + assert(result); + + // not found case + result = contains(arr, 10); + assert(!result); + } + { // unreachable_sentinel case + const In wrapped{haystack}; + const same_as auto result = contains(begin(wrapped), unreachable_sentinel, 2, get_first); + assert(result); + } + } +}; + +int main() { + STATIC_ASSERT((test_in>(), true)); + test_in>(); +} diff --git a/tests/std/tests/P2302R3_ranges_alg_contains_subrange/env.lst b/tests/std/tests/P2302R3_ranges_alg_contains_subrange/env.lst new file mode 100644 index 0000000000..18e2d7c71e --- /dev/null +++ b/tests/std/tests/P2302R3_ranges_alg_contains_subrange/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P2302R3_ranges_alg_contains_subrange/test.cpp b/tests/std/tests/P2302R3_ranges_alg_contains_subrange/test.cpp new file mode 100644 index 0000000000..8700a704df --- /dev/null +++ b/tests/std/tests/P2302R3_ranges_alg_contains_subrange/test.cpp @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +#include + +using namespace std; + +using Elem1 = const pair; +using Elem2 = const int; + +struct instantiator { + static constexpr pair haystack[] = {{0, 42}, {1, 42}, {2, 42}, {3, 42}, {4, 42}, {5, 42}}; + static constexpr int needle[] = {2, 3, 4}; + + template + static constexpr void call() { + using ranges::contains_subrange, ranges::begin, ranges::end; + + { // Validate range overload [found case] + const same_as auto result = + contains_subrange(Fwd1{haystack}, Fwd2{needle}, ranges::equal_to{}, get_first); + assert(result); + } + { // Validate iterator + sentinel overload [found case] + const Fwd1 wrap_hay{haystack}; + const Fwd2 wrap_needle{needle}; + const same_as auto result = contains_subrange( + begin(wrap_hay), end(wrap_hay), begin(wrap_needle), end(wrap_needle), ranges::equal_to{}, get_first); + assert(result); + } + { // Validate range overload [not found case] + const same_as auto result = + contains_subrange(Fwd1{haystack}, Fwd2{needle}, ranges::equal_to{}, get_second); + assert(!result); + } + { // Validate iterator + sentinel overload [not found case] + const Fwd1 wrap_hay{haystack}; + const Fwd2 wrap_needle{needle}; + const same_as auto result = contains_subrange( + begin(wrap_hay), end(wrap_hay), begin(wrap_needle), end(wrap_needle), ranges::equal_to{}, get_second); + assert(!result); + } + { // Validate empty needle case + const span empty; + const same_as auto result = contains_subrange(Fwd1{haystack}, Fwd1{empty}); + assert(result); + } + { // Validate unreachable_sentinel case + const Fwd1 wrap_hay{haystack}; + const Fwd2 wrap_needle{needle}; + const same_as auto result = contains_subrange(begin(wrap_hay), unreachable_sentinel, + begin(wrap_needle), end(wrap_needle), ranges::equal_to{}, get_first); + assert(result); + } + } +}; + +#ifdef TEST_EVERYTHING +int main() { + STATIC_ASSERT((test_fwd_fwd(), true)); + test_fwd_fwd(); +} +#else // ^^^ test all range combinations // test only interesting range combos vvv +template +using fwd_test_range = test::range; +template +using random_test_range = test::range; + +constexpr bool run_tests() { + // All (except contiguous) proxy reference types, since the algorithm doesn't really care. Cases with only 1 range + // sized are not interesting; common is interesting only in that it's necessary to trigger memcmp optimization. + + using test::Common, test::Sized; + + // both forward, non-common, and sized or unsized + instantiator::call, fwd_test_range>(); + instantiator::call, fwd_test_range>(); + + // both random-access, and sized or unsized; all permutations of common + instantiator::call, + random_test_range>(); + instantiator::call, + random_test_range>(); + instantiator::call, + random_test_range>(); + instantiator::call, + random_test_range>(); + instantiator::call, + random_test_range>(); + instantiator::call, + random_test_range>(); + instantiator::call, + random_test_range>(); + instantiator::call, + random_test_range>(); + + return true; +} + +int main() { + STATIC_ASSERT(run_tests()); + run_tests(); +} +#endif // TEST_EVERYTHING diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 34ca2d2adb..cba8cf2734 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -1408,6 +1408,20 @@ STATIC_ASSERT(__cpp_lib_ranges_chunk_by == 202202L); #endif #endif +#if _HAS_CXX23 && !defined(__EDG__) // TRANSITION, EDG concepts support +#ifndef __cpp_lib_ranges_contains +#error __cpp_lib_ranges_contains is not defined +#elif __cpp_lib_ranges_contains != 202207L +#error __cpp_lib_ranges_contains is not 202207L +#else +STATIC_ASSERT(__cpp_lib_ranges_contains == 202207L); +#endif +#else +#ifdef __cpp_lib_ranges_contains +#error __cpp_lib_ranges_contains is defined +#endif +#endif + #if _HAS_CXX23 && defined(__cpp_lib_concepts) #ifndef __cpp_lib_ranges_iota #error __cpp_lib_ranges_iota is not defined From 9056cd81fbae514182672f74a7c30a6c32206a0b Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Mon, 25 Jul 2022 19:01:39 +0100 Subject: [PATCH 2/8] Formatting --- stl/inc/yvals_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index f1aaf1083c..e17996a467 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1463,7 +1463,7 @@ #define __cpp_lib_out_ptr 202106L #define __cpp_lib_ranges_chunk 202202L #define __cpp_lib_ranges_chunk_by 202202L -#define __cpp_lib_ranges_contains 202207L +#define __cpp_lib_ranges_contains 202207L #define __cpp_lib_ranges_iota 202202L #define __cpp_lib_ranges_join_with 202202L #define __cpp_lib_ranges_slide 202202L From 7070ab56150608d05d9d48c751dd139bed1da19c Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Mon, 25 Jul 2022 19:33:46 +0100 Subject: [PATCH 3/8] Fix revision number [skip ci] --- stl/inc/yvals_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index e17996a467..a9ec679443 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -309,7 +309,7 @@ // P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr // P2186R2 Removing Garbage Collection Support // P2273R3 constexpr unique_ptr -// P2302R3 ranges::contains +// P2302R4 ranges::contains // P2321R2 zip // (changes to pair, tuple, and vector::reference only) // P2440R1 ranges::iota, ranges::shift_left, ranges::shift_right From 2a36ffa6f67d83e279c257fa8c2faf340f6f2705 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 26 Jul 2022 18:51:35 -0700 Subject: [PATCH 4/8] Update test directories to R4. --- .../env.lst | 0 .../test.cpp | 0 .../env.lst | 0 .../test.cpp | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename tests/std/tests/{P2302R3_ranges_alg_contains => P2302R4_ranges_alg_contains}/env.lst (100%) rename tests/std/tests/{P2302R3_ranges_alg_contains => P2302R4_ranges_alg_contains}/test.cpp (100%) rename tests/std/tests/{P2302R3_ranges_alg_contains_subrange => P2302R4_ranges_alg_contains_subrange}/env.lst (100%) rename tests/std/tests/{P2302R3_ranges_alg_contains_subrange => P2302R4_ranges_alg_contains_subrange}/test.cpp (100%) diff --git a/tests/std/tests/P2302R3_ranges_alg_contains/env.lst b/tests/std/tests/P2302R4_ranges_alg_contains/env.lst similarity index 100% rename from tests/std/tests/P2302R3_ranges_alg_contains/env.lst rename to tests/std/tests/P2302R4_ranges_alg_contains/env.lst diff --git a/tests/std/tests/P2302R3_ranges_alg_contains/test.cpp b/tests/std/tests/P2302R4_ranges_alg_contains/test.cpp similarity index 100% rename from tests/std/tests/P2302R3_ranges_alg_contains/test.cpp rename to tests/std/tests/P2302R4_ranges_alg_contains/test.cpp diff --git a/tests/std/tests/P2302R3_ranges_alg_contains_subrange/env.lst b/tests/std/tests/P2302R4_ranges_alg_contains_subrange/env.lst similarity index 100% rename from tests/std/tests/P2302R3_ranges_alg_contains_subrange/env.lst rename to tests/std/tests/P2302R4_ranges_alg_contains_subrange/env.lst diff --git a/tests/std/tests/P2302R3_ranges_alg_contains_subrange/test.cpp b/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp similarity index 100% rename from tests/std/tests/P2302R3_ranges_alg_contains_subrange/test.cpp rename to tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp From 2d9d7256c8f4f430195bc8d1f40814982287cb83 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 26 Jul 2022 19:06:13 -0700 Subject: [PATCH 5/8] Code review feedback. --- stl/inc/algorithm | 10 ++++++---- stl/inc/yvals_core.h | 2 +- tests/std/test.lst | 2 ++ tests/std/tests/P2302R4_ranges_alg_contains/test.cpp | 1 + .../P2302R4_ranges_alg_contains_subrange/test.cpp | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index e1f8d8ac9f..570785d18f 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1364,6 +1364,7 @@ namespace ranges { inline constexpr _None_of_fn none_of{_Not_quite_object::_Construct_tag{}}; +#if _HAS_CXX23 class _Contains_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -1378,7 +1379,7 @@ namespace ranges { requires indirect_binary_predicate < ranges::equal_to, projected, _Pj>, const _Ty* > // _NODISCARD constexpr bool operator()(_Rng&& _Range, const _Ty& _Val, _Pj _Proj = {}) const { - return (*this)(_RANGES begin(_Range), _RANGES end(_Range), _Val, _Pass_fn(_Proj)); + return (*this)(_Ubegin(_Range), _Uend(_Range), _Val, _Pass_fn(_Proj)); } }; @@ -1394,7 +1395,7 @@ namespace ranges { _NODISCARD constexpr bool operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { return _First2 == _Last2 - || !ranges::search( + || !_RANGES search( _First1, _Last1, _First2, _Last2, _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)) .empty(); } @@ -1403,12 +1404,13 @@ namespace ranges { requires indirectly_comparable, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2> // _NODISCARD constexpr bool operator()( _Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { - return (*this)(_RANGES begin(_Range1), _RANGES end(_Range1), _RANGES begin(_Range2), _RANGES end(_Range2), - _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)); + return (*this)(_Ubegin(_Range1), _Uend(_Range1), _Ubegin(_Range2), _Uend(_Range2), _Pass_fn(_Pred), + _Pass_fn(_Proj1), _Pass_fn(_Proj2)); } }; inline constexpr _Contains_subrange_fn contains_subrange{_Not_quite_object::_Construct_tag{}}; +#endif // _HAS_CXX23 template using copy_n_result = in_out_result<_In, _Out>; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index a9ec679443..4d5aece700 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -309,7 +309,7 @@ // P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr // P2186R2 Removing Garbage Collection Support // P2273R3 constexpr unique_ptr -// P2302R4 ranges::contains +// P2302R4 ranges::contains, ranges::contains_subrange // P2321R2 zip // (changes to pair, tuple, and vector::reference only) // P2440R1 ranges::iota, ranges::shift_left, ranges::shift_right diff --git a/tests/std/test.lst b/tests/std/test.lst index 5121260b7f..15b0eb8f76 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -486,6 +486,8 @@ tests\P2136R3_invoke_r tests\P2162R2_std_visit_for_derived_classes_from_variant tests\P2231R1_complete_constexpr_optional_variant tests\P2273R3_constexpr_unique_ptr +tests\P2302R4_ranges_alg_contains +tests\P2302R4_ranges_alg_contains_subrange tests\P2321R2_proxy_reference tests\P2401R0_conditional_noexcept_for_exchange tests\P2415R2_owning_view diff --git a/tests/std/tests/P2302R4_ranges_alg_contains/test.cpp b/tests/std/tests/P2302R4_ranges_alg_contains/test.cpp index fcfcda10e5..706c744cf3 100644 --- a/tests/std/tests/P2302R4_ranges_alg_contains/test.cpp +++ b/tests/std/tests/P2302R4_ranges_alg_contains/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include diff --git a/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp b/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp index 8700a704df..f1b4fc6e52 100644 --- a/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp +++ b/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp @@ -51,7 +51,7 @@ struct instantiator { const same_as auto result = contains_subrange(Fwd1{haystack}, Fwd1{empty}); assert(result); } - { // Validate unreachable_sentinel case + { // Validate unreachable_sentinel case const Fwd1 wrap_hay{haystack}; const Fwd2 wrap_needle{needle}; const same_as auto result = contains_subrange(begin(wrap_hay), unreachable_sentinel, From 582948496679e1c962671b46a91d12617c80c0af Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Wed, 27 Jul 2022 07:59:24 +0100 Subject: [PATCH 6/8] Constrain template params in contains_subrange test. --- tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp b/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp index f1b4fc6e52..7e6daf2a43 100644 --- a/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp +++ b/tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp @@ -18,7 +18,7 @@ struct instantiator { static constexpr pair haystack[] = {{0, 42}, {1, 42}, {2, 42}, {3, 42}, {4, 42}, {5, 42}}; static constexpr int needle[] = {2, 3, 4}; - template + template static constexpr void call() { using ranges::contains_subrange, ranges::begin, ranges::end; From 294ece7445a90b621fedf13f707cc7e89e55191e Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 27 Jul 2022 11:33:17 -0700 Subject: [PATCH 7/8] Casey's and miscco's review comments --- stl/inc/algorithm | 64 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 570785d18f..8911043509 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1369,17 +1369,25 @@ namespace ranges { public: using _Not_quite_object::_Not_quite_object; + // clang-format off template _Se, class _Ty, class _Pj = identity> - requires indirect_binary_predicate < ranges::equal_to, projected<_It, _Pj>, - const _Ty* > // - _NODISCARD constexpr bool operator()(_It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) const { - return _RANGES find(_STD move(_First), _Last, _Val, _Pass_fn(_Proj)) != _Last; + requires indirect_binary_predicate, const _Ty*> + _NODISCARD constexpr bool operator()(_It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) const { + // clang-format on + _Adl_verify_range(_First, _Last); + const auto _ULast = _Get_unwrapped(_STD move(_Last)); + const auto _UResult = + _RANGES _Find_unchecked(_Get_unwrapped(_STD move(_First)), _ULast, _Val, _Pass_fn(_Proj)); + return _UResult != _ULast; } + + // clang-format off template - requires indirect_binary_predicate < ranges::equal_to, projected, _Pj>, - const _Ty* > // - _NODISCARD constexpr bool operator()(_Rng&& _Range, const _Ty& _Val, _Pj _Proj = {}) const { - return (*this)(_Ubegin(_Range), _Uend(_Range), _Val, _Pass_fn(_Proj)); + requires indirect_binary_predicate, _Pj>, const _Ty*> + _NODISCARD constexpr bool operator()(_Rng&& _Range, const _Ty& _Val, _Pj _Proj = {}) const { + // clang-format on + const auto _UResult = _RANGES _Find_unchecked(_Ubegin(_Range), _Uend(_Range), _Val, _Pass_fn(_Proj)); + return _UResult != _Uend(_Range); } }; @@ -1389,23 +1397,39 @@ namespace ranges { public: using _Not_quite_object::_Not_quite_object; + // clang-format off template _Se1, forward_iterator _It2, sentinel_for<_It2> _Se2, class _Pr = ranges::equal_to, class _Pj1 = identity, class _Pj2 = identity> - requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2> // - _NODISCARD constexpr bool operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred = {}, - _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { - return _First2 == _Last2 - || !_RANGES search( - _First1, _Last1, _First2, _Last2, _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)) - .empty(); + requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2> + _NODISCARD constexpr bool operator()(_It1 _First1, + _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { + // clang-format on + _Adl_verify_range(_First2, _Last2); + auto _UFirst2 = _Get_unwrapped(_STD move(_First2)); + auto _ULast2 = _Get_unwrapped(_STD move(_Last2)); + + if (_UFirst2 == _ULast2) { + return true; + } + + const auto _Match = _RANGES search(_First1, _Last1, _STD move(_UFirst2), _STD move(_ULast2), + _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)); + return !_Match.empty(); } + + // clang-format off template - requires indirectly_comparable, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2> // - _NODISCARD constexpr bool operator()( - _Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { - return (*this)(_Ubegin(_Range1), _Uend(_Range1), _Ubegin(_Range2), _Uend(_Range2), _Pass_fn(_Pred), - _Pass_fn(_Proj1), _Pass_fn(_Proj2)); + requires indirectly_comparable, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2> + _NODISCARD constexpr bool operator()( + _Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const { + // clang-format on + if (_RANGES empty(_Range2)) { + return true; + } + + const auto _Match = _RANGES search(_Range1, _Range2, _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)); + return !_Match.empty(); } }; From e93bd15cf53a1d821433fa22ffe343233865341c Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 27 Jul 2022 11:47:22 -0700 Subject: [PATCH 8/8] I like to move it move it --- stl/inc/algorithm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 8911043509..9f4ffcd1fb 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1412,8 +1412,8 @@ namespace ranges { return true; } - const auto _Match = _RANGES search(_First1, _Last1, _STD move(_UFirst2), _STD move(_ULast2), - _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)); + const auto _Match = _RANGES search(_STD move(_First1), _STD move(_Last1), _STD move(_UFirst2), + _STD move(_ULast2), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2)); return !_Match.empty(); }