[libc++] Bring std::{any,all,none}_of tests up to current standards#209266
Open
ldionne wants to merge 1 commit into
Open
[libc++] Bring std::{any,all,none}_of tests up to current standards#209266ldionne wants to merge 1 commit into
ldionne wants to merge 1 commit into
Conversation
The tests for these algorithms were minimal, didn't test all iterator categories, and the constexpr coverage didn't follow our current practice. This patch brings all three tests (which are very similar) up to our current standards. Assisted by Claude
|
@llvm/pr-subscribers-libcxx Author: Louis Dionne (ldionne) ChangesThe tests for these algorithms were minimal, didn't test all iterator categories, and the constexpr coverage didn't follow our current practice. This patch brings all three tests (which are very similar) up to our current standards. Assisted by Claude Full diff: https://github.com/llvm/llvm-project/pull/209266.diff 3 Files Affected:
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/all_of.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/all_of.pass.cpp
index f9377fb10277f..acbdeda0f82e6 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/all_of.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/all_of.pass.cpp
@@ -9,55 +9,90 @@
// <algorithm>
// template <class InputIterator, class Predicate>
-// constexpr bool // constexpr after C++17
-// all_of(InputIterator first, InputIterator last, Predicate pred);
+// constexpr bool all_of(InputIterator first, InputIterator last, Predicate pred); // constexpr since C++20
#include <algorithm>
#include <cassert>
-#include <iterator>
#include "test_macros.h"
#include "test_iterators.h"
+#include "type_algorithms.h"
-struct test1
-{
- TEST_CONSTEXPR bool operator()(const int& i) const
- {
- return i % 2 == 0;
- }
+struct is_odd {
+ TEST_CONSTEXPR bool operator()(const int& i) const { return i % 2 != 0; }
+};
+
+struct counting_predicate {
+ int* times_applied;
+ bool result;
+ TEST_CONSTEXPR counting_predicate(int* counter, bool r) : times_applied(counter), result(r) {}
+ TEST_CONSTEXPR_CXX14 bool operator()(int) const {
+ ++*times_applied;
+ return result;
+ }
};
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
- int ia[] = {2, 4, 6, 8};
- int ib[] = {2, 4, 5, 8};
- return std::all_of(std::begin(ia), std::end(ia), test1())
- && !std::all_of(std::begin(ib), std::end(ib), test1())
- ;
+struct Test {
+ template <class Iter>
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ { // an empty range vacuously satisfies the predicate
+ int a[] = {2, 4, 6, 8};
+ // The return type is always `bool`, regardless of the iterator category.
+ ASSERT_SAME_TYPE(bool, decltype(std::all_of(Iter(a), Iter(a), is_odd())));
+ assert(std::all_of(Iter(a), Iter(a), is_odd()));
+ }
+
+ { // every element satisfies the predicate
+ int a[] = {1, 3, 5, 7};
+ assert(std::all_of(Iter(a), Iter(a + 4), is_odd()));
+ }
+
+ { // no element satisfies the predicate
+ int a[] = {2, 4, 6, 8};
+ assert(!std::all_of(Iter(a), Iter(a + 4), is_odd()));
+ }
+
+ { // the only non-satisfying element is the first one
+ int a[] = {2, 1, 3, 5};
+ assert(!std::all_of(Iter(a), Iter(a + 4), is_odd()));
}
-#endif
-int main(int, char**)
-{
- {
- int ia[] = {2, 4, 6, 8};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::all_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == true);
- assert(std::all_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == true);
+ { // the only non-satisfying element is in the middle
+ int a[] = {1, 3, 4, 5};
+ assert(!std::all_of(Iter(a), Iter(a + 4), is_odd()));
}
- {
- const int ia[] = {2, 4, 5, 8};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::all_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == false);
- assert(std::all_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == true);
+
+ { // the only non-satisfying element is the last one
+ int a[] = {1, 3, 5, 8};
+ assert(!std::all_of(Iter(a), Iter(a + 4), is_odd()));
}
-#if TEST_STD_VER > 17
- static_assert(test_constexpr());
+ { // a single-element range, satisfying and not satisfying the predicate
+ int satisfies = 1;
+ int not_satisfies = 2;
+ assert(std::all_of(Iter(&satisfies), Iter(&satisfies + 1), is_odd()));
+ assert(!std::all_of(Iter(¬_satisfies), Iter(¬_satisfies + 1), is_odd()));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ types::for_each(types::cpp17_input_iterator_list<int*>(), Test());
+
+ { // the predicate is applied at most `last - first` times (complexity requirement)
+ int a[] = {1, 2, 3, 4, 5};
+ int applied = 0;
+ assert(std::all_of(a, a + 5, counting_predicate(&applied, true)));
+ assert(applied == 5);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
#endif
return 0;
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/any_of.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/any_of.pass.cpp
index c0b659304db8b..6eb815d4bf652 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/any_of.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/any_of.pass.cpp
@@ -9,63 +9,90 @@
// <algorithm>
// template <class InputIterator, class Predicate>
-// constexpr bool // constexpr after C++17
-// any_of(InputIterator first, InputIterator last, Predicate pred);
+// constexpr bool any_of(InputIterator first, InputIterator last, Predicate pred); // constexpr since C++20
#include <algorithm>
#include <cassert>
-#include <iterator>
#include "test_macros.h"
#include "test_iterators.h"
+#include "type_algorithms.h"
-struct test1
-{
- TEST_CONSTEXPR bool operator()(const int& i) const
- {
- return i % 2 == 0;
- }
+struct is_odd {
+ TEST_CONSTEXPR bool operator()(const int& i) const { return i % 2 != 0; }
+};
+
+struct counting_predicate {
+ int* times_applied;
+ bool result;
+ TEST_CONSTEXPR counting_predicate(int* counter, bool r) : times_applied(counter), result(r) {}
+ TEST_CONSTEXPR_CXX14 bool operator()(int) const {
+ ++*times_applied;
+ return result;
+ }
};
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
- int ia[] = {2, 4, 6, 8};
- int ib[] = {1, 3, 5, 7};
- return std::any_of(std::begin(ia), std::end(ia), test1())
- && !std::any_of(std::begin(ib), std::end(ib), test1())
- ;
+struct Test {
+ template <class Iter>
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ { // an empty range never contains a matching element
+ int a[] = {1, 2, 3, 4};
+ // The return type is always `bool`, regardless of the iterator category.
+ ASSERT_SAME_TYPE(bool, decltype(std::any_of(Iter(a), Iter(a), is_odd())));
+ assert(!std::any_of(Iter(a), Iter(a), is_odd()));
}
-#endif
-int main(int, char**)
-{
- {
- int ia[] = {2, 4, 6, 8};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::any_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == true);
- assert(std::any_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == false);
+ { // no element matches the predicate
+ int a[] = {2, 4, 6, 8};
+ assert(!std::any_of(Iter(a), Iter(a + 4), is_odd()));
}
- {
- const int ia[] = {2, 4, 5, 8};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::any_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == true);
- assert(std::any_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == false);
+
+ { // every element matches the predicate
+ int a[] = {1, 3, 5, 7};
+ assert(std::any_of(Iter(a), Iter(a + 4), is_odd()));
}
- {
- const int ia[] = {1, 3, 5, 7};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::any_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == false);
- assert(std::any_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == false);
+
+ { // the only matching element is the first one
+ int a[] = {1, 2, 4, 6};
+ assert(std::any_of(Iter(a), Iter(a + 4), is_odd()));
+ }
+
+ { // the only matching element is in the middle
+ int a[] = {2, 4, 5, 8};
+ assert(std::any_of(Iter(a), Iter(a + 4), is_odd()));
}
-#if TEST_STD_VER > 17
- static_assert(test_constexpr());
+ { // the only matching element is the last one
+ int a[] = {2, 4, 6, 7};
+ assert(std::any_of(Iter(a), Iter(a + 4), is_odd()));
+ }
+
+ { // a single-element range, with and without a match
+ int match = 1;
+ int no_match = 2;
+ assert(std::any_of(Iter(&match), Iter(&match + 1), is_odd()));
+ assert(!std::any_of(Iter(&no_match), Iter(&no_match + 1), is_odd()));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ types::for_each(types::cpp17_input_iterator_list<int*>(), Test());
+
+ { // the predicate is applied at most `last - first` times (complexity requirement)
+ int a[] = {1, 2, 3, 4, 5};
+ int applied = 0;
+ assert(!std::any_of(a, a + 5, counting_predicate(&applied, false)));
+ assert(applied == 5);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
#endif
return 0;
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/none_of.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/none_of.pass.cpp
index 8d63ecb6c17a5..4a1c5c5bd5c4d 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/none_of.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/none_of.pass.cpp
@@ -9,63 +9,90 @@
// <algorithm>
// template <class InputIterator, class Predicate>
-// bool
-// none_of(InputIterator first, InputIterator last, Predicate pred);
+// constexpr bool none_of(InputIterator first, InputIterator last, Predicate pred); // constexpr since C++20
#include <algorithm>
#include <cassert>
-#include <iterator>
#include "test_macros.h"
#include "test_iterators.h"
+#include "type_algorithms.h"
-struct test1
-{
- TEST_CONSTEXPR bool operator()(const int& i) const
- {
- return i % 2 == 0;
- }
+struct is_odd {
+ TEST_CONSTEXPR bool operator()(const int& i) const { return i % 2 != 0; }
+};
+
+struct counting_predicate {
+ int* times_applied;
+ bool result;
+ TEST_CONSTEXPR counting_predicate(int* counter, bool r) : times_applied(counter), result(r) {}
+ TEST_CONSTEXPR_CXX14 bool operator()(int) const {
+ ++*times_applied;
+ return result;
+ }
};
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
- int ia[] = {1, 3, 6, 7};
- int ib[] = {1, 3, 5, 7};
- return !std::none_of(std::begin(ia), std::end(ia), test1())
- && std::none_of(std::begin(ib), std::end(ib), test1())
- ;
+struct Test {
+ template <class Iter>
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ { // an empty range vacuously satisfies none_of
+ int a[] = {1, 3, 5, 7};
+ // The return type is always `bool`, regardless of the iterator category.
+ ASSERT_SAME_TYPE(bool, decltype(std::none_of(Iter(a), Iter(a), is_odd())));
+ assert(std::none_of(Iter(a), Iter(a), is_odd()));
}
-#endif
-int main(int, char**)
-{
- {
- int ia[] = {2, 4, 6, 8};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::none_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == false);
- assert(std::none_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == true);
+ { // no element satisfies the predicate
+ int a[] = {2, 4, 6, 8};
+ assert(std::none_of(Iter(a), Iter(a + 4), is_odd()));
}
- {
- const int ia[] = {2, 4, 5, 8};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::none_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == false);
- assert(std::none_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == true);
+
+ { // every element satisfies the predicate
+ int a[] = {1, 3, 5, 7};
+ assert(!std::none_of(Iter(a), Iter(a + 4), is_odd()));
}
- {
- const int ia[] = {1, 3, 5, 7};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- assert(std::none_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia + sa), test1()) == true);
- assert(std::none_of(cpp17_input_iterator<const int*>(ia),
- cpp17_input_iterator<const int*>(ia), test1()) == true);
+
+ { // the only satisfying element is the first one
+ int a[] = {1, 2, 4, 6};
+ assert(!std::none_of(Iter(a), Iter(a + 4), is_odd()));
+ }
+
+ { // the only satisfying element is in the middle
+ int a[] = {2, 4, 5, 8};
+ assert(!std::none_of(Iter(a), Iter(a + 4), is_odd()));
}
-#if TEST_STD_VER > 17
- static_assert(test_constexpr());
+ { // the only satisfying element is the last one
+ int a[] = {2, 4, 6, 7};
+ assert(!std::none_of(Iter(a), Iter(a + 4), is_odd()));
+ }
+
+ { // a single-element range, satisfying and not satisfying the predicate
+ int satisfies = 1;
+ int not_satisfies = 2;
+ assert(!std::none_of(Iter(&satisfies), Iter(&satisfies + 1), is_odd()));
+ assert(std::none_of(Iter(¬_satisfies), Iter(¬_satisfies + 1), is_odd()));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ types::for_each(types::cpp17_input_iterator_list<int*>(), Test());
+
+ { // the predicate is applied at most `last - first` times (complexity requirement)
+ int a[] = {1, 2, 3, 4, 5};
+ int applied = 0;
+ assert(std::none_of(a, a + 5, counting_predicate(&applied, false)));
+ assert(applied == 5);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
#endif
return 0;
|
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The tests for these algorithms were minimal, didn't test all iterator categories, and the constexpr coverage didn't follow our current practice. This patch brings all three tests (which are very similar) up to our current standards.
Assisted by Claude