-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
<algorithm> Implement P2302R4 ranges::contains (#2911)
Co-authored-by: Stephan T. Lavavej <[email protected]> Co-authored-by: Casey Carter <[email protected]>
- Loading branch information
1 parent
9974091
commit f8a9c6f
Showing
8 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
RUNALL_INCLUDE ..\concepts_latest_matrix.lst |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
#include <algorithm> | ||
#include <cassert> | ||
#include <concepts> | ||
#include <ranges> | ||
#include <utility> | ||
|
||
#include <range_algorithm_support.hpp> | ||
|
||
using namespace std; | ||
|
||
struct instantiator { | ||
static constexpr pair<int, int> haystack[3] = {{0, 42}, {2, 42}, {4, 42}}; | ||
|
||
template <ranges::input_range In> | ||
static constexpr void call() { | ||
using ranges::contains, ranges::begin, ranges::end; | ||
|
||
for (const auto& [value, _] : haystack) { | ||
{ // Validate range overload [found case] | ||
const same_as<bool> auto result = contains(In{haystack}, value, get_first); | ||
assert(result); | ||
} | ||
{ // Validate iterator + sentinel overload [found case] | ||
const In wrapped{haystack}; | ||
const same_as<bool> auto result = contains(begin(wrapped), end(wrapped), value, get_first); | ||
assert(result); | ||
} | ||
} | ||
{ | ||
// Validate range overload [not found case] | ||
const same_as<bool> auto result = contains(In{haystack}, 42, get_first); | ||
assert(!result); | ||
} | ||
{ | ||
// Validate iterator + sentinel overload [not found case] | ||
const In wrapped{haystack}; | ||
const same_as<bool> 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<bool> 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<bool> auto result = contains(begin(wrapped), unreachable_sentinel, 2, get_first); | ||
assert(result); | ||
} | ||
} | ||
}; | ||
|
||
int main() { | ||
STATIC_ASSERT((test_in<instantiator, const pair<int, int>>(), true)); | ||
test_in<instantiator, const pair<int, int>>(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
RUNALL_INCLUDE ..\concepts_latest_matrix.lst |
112 changes: 112 additions & 0 deletions
112
tests/std/tests/P2302R4_ranges_alg_contains_subrange/test.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
#include <algorithm> | ||
#include <cassert> | ||
#include <concepts> | ||
#include <span> | ||
#include <utility> | ||
|
||
#include <range_algorithm_support.hpp> | ||
|
||
using namespace std; | ||
|
||
using Elem1 = const pair<int, int>; | ||
using Elem2 = const int; | ||
|
||
struct instantiator { | ||
static constexpr pair<int, int> haystack[] = {{0, 42}, {1, 42}, {2, 42}, {3, 42}, {4, 42}, {5, 42}}; | ||
static constexpr int needle[] = {2, 3, 4}; | ||
|
||
template <ranges::forward_range Fwd1, ranges::forward_range Fwd2> | ||
static constexpr void call() { | ||
using ranges::contains_subrange, ranges::begin, ranges::end; | ||
|
||
{ // Validate range overload [found case] | ||
const same_as<bool> 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<bool> 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<bool> 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<bool> 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<Elem1> empty; | ||
const same_as<bool> 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<bool> 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<instantiator, Elem1, Elem2>(), true)); | ||
test_fwd_fwd<instantiator, Elem1, Elem2>(); | ||
} | ||
#else // ^^^ test all range combinations // test only interesting range combos vvv | ||
template <class Elem, test::Sized IsSized> | ||
using fwd_test_range = test::range<forward_iterator_tag, Elem, IsSized, test::CanDifference::no, test::Common::no, | ||
test::CanCompare::yes, test::ProxyRef::yes>; | ||
template <class Elem, test::Sized IsSized, test::Common IsCommon> | ||
using random_test_range = test::range<random_access_iterator_tag, Elem, IsSized, test::CanDifference::no, IsCommon, | ||
test::CanCompare::yes, test::ProxyRef::no>; | ||
|
||
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<Elem1, Sized::no>, fwd_test_range<Elem2, Sized::no>>(); | ||
instantiator::call<fwd_test_range<Elem1, Sized::yes>, fwd_test_range<Elem2, Sized::yes>>(); | ||
|
||
// both random-access, and sized or unsized; all permutations of common | ||
instantiator::call<random_test_range<Elem1, Sized::no, Common::no>, | ||
random_test_range<Elem2, Sized::no, Common::no>>(); | ||
instantiator::call<random_test_range<Elem1, Sized::no, Common::no>, | ||
random_test_range<Elem2, Sized::no, Common::yes>>(); | ||
instantiator::call<random_test_range<Elem1, Sized::no, Common::yes>, | ||
random_test_range<Elem2, Sized::no, Common::no>>(); | ||
instantiator::call<random_test_range<Elem1, Sized::no, Common::yes>, | ||
random_test_range<Elem2, Sized::no, Common::yes>>(); | ||
instantiator::call<random_test_range<Elem1, Sized::yes, Common::no>, | ||
random_test_range<Elem2, Sized::yes, Common::no>>(); | ||
instantiator::call<random_test_range<Elem1, Sized::yes, Common::no>, | ||
random_test_range<Elem2, Sized::yes, Common::yes>>(); | ||
instantiator::call<random_test_range<Elem1, Sized::yes, Common::yes>, | ||
random_test_range<Elem2, Sized::yes, Common::no>>(); | ||
instantiator::call<random_test_range<Elem1, Sized::yes, Common::yes>, | ||
random_test_range<Elem2, Sized::yes, Common::yes>>(); | ||
|
||
return true; | ||
} | ||
|
||
int main() { | ||
STATIC_ASSERT(run_tests()); | ||
run_tests(); | ||
} | ||
#endif // TEST_EVERYTHING |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters