[libcxx-commits] [libcxx] 033f550 - [libc++][pstl] Add serial implementations of the set operations (#233783)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Oct 23 01:45:52 PDT 2026
Author: Michael G. Kazakov
Date: 2026-10-23T09:45:47+01:00
New Revision: 033f55044e278cda13e7a1472ab1fd7a4f9c0936
URL: https://github.com/llvm/llvm-project/commit/033f55044e278cda13e7a1472ab1fd7a4f9c0936
DIFF: https://github.com/llvm/llvm-project/commit/033f55044e278cda13e7a1472ab1fd7a4f9c0936.diff
LOG: [libc++][pstl] Add serial implementations of the set operations (#233783)
This PR adds serial implementations of the set operations to PSTL.
They are added to the serial backend only, such that any other one can
fall back to these implementations.
Currently there's no intent to provide parallel versions of these
algorithms, but later they can be added as well.
These are the added set operations:
- `std::includes`
- `std::set_union`
- `std::set_intersection`
- `std::set_difference`
- `std::set_symmetric_difference`
Part of #99938.
Added:
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes_comp.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/pstl.set_difference.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/pstl.set_difference_comp.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection_comp.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/pstl.set_symmetric_difference.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/pstl.set_symmetric_difference_comp.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union_comp.pass.cpp
Modified:
libcxx/include/__algorithm/pstl.h
libcxx/include/__pstl/backend_fwd.h
libcxx/include/__pstl/backends/serial.h
libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index 66fa8b3cdd8a00..dc0e5d5a946b19 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -1210,6 +1210,288 @@ is_sorted_until(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardI
std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__comp));
}
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] bool
+includes(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "includes requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "includes requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__includes, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ less{});
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _Compare,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] bool
+includes(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _Compare __comp) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "includes requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "includes requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__includes, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__comp));
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator
+set_union(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_union requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_union requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_union requires result to be an OutputIterator");
+ using _Implementation = __pstl::__dispatch<__pstl::__set_union, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ less{});
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _Compare,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator
+set_union(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_union requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_union requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_union requires result to be an OutputIterator");
+ using _Implementation = __pstl::__dispatch<__pstl::__set_union, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator set_intersection(
+ _ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_intersection requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_intersection requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_intersection requires result to be an OutputIterator");
+ using _Implementation = __pstl::__dispatch<__pstl::__set_intersection, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ less{});
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _Compare,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator set_intersection(
+ _ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_intersection requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_intersection requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_intersection requires result to be an OutputIterator");
+ using _Implementation = __pstl::__dispatch<__pstl::__set_intersection, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator set_
diff erence(
+ _ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_
diff erence requires result to be an OutputIterator");
+ using _Implementation = __pstl::__dispatch<__pstl::__set_
diff erence, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ less{});
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _Compare,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator set_
diff erence(
+ _ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_
diff erence requires result to be an OutputIterator");
+ using _Implementation = __pstl::__dispatch<__pstl::__set_
diff erence, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator set_symmetric_
diff erence(
+ _ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_symmetric_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_symmetric_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_symmetric_
diff erence requires result to be an OutputIterator");
+ using _Implementation =
+ __pstl::__dispatch<__pstl::__set_symmetric_
diff erence, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ less{});
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _ForwardOutIterator,
+ class _Compare,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _ForwardOutIterator set_symmetric_
diff erence(
+ _ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "set_symmetric_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "set_symmetric_
diff erence requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(
+ _ForwardOutIterator, decltype(*__first1), "set_symmetric_
diff erence requires result to be an OutputIterator");
+ using _Implementation =
+ __pstl::__dispatch<__pstl::__set_symmetric_
diff erence, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+}
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_HAS_EXPERIMENTAL_PSTL && _LIBCPP_STD_VER >= 17
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index 4a560259d0dfc2..fbc6f9920bdedd 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -214,6 +214,14 @@ struct __generate_n;
// optional<_ForwardIterator>
// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Generator __gen) const noexcept;
+template <class _Backend, class _ExecutionPolicy>
+struct __includes;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Compare>
+// optional<bool>
+// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+// _Compare __comp) const noexcept;
+
template <class _Backend, class _ExecutionPolicy>
struct __is_heap;
// template <class _Policy, class _RandomAccessIterator, class _Comp>
@@ -380,6 +388,42 @@ struct __search_n;
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _Size __count, const _T& __value, _Predicate __pred) const noexcept;
+template <class _Backend, class _ExecutionPolicy>
+struct __set_
diff erence;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+// optional<_ForwardOutIterator>
+// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+// _ForwardOutIterator __result,
+// _Compare __comp) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __set_intersection;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+// optional<_ForwardOutIterator>
+// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+// _ForwardOutIterator __result,
+// _Compare __comp) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __set_symmetric_
diff erence;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+// optional<_ForwardOutIterator>
+// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+// _ForwardOutIterator __result,
+// _Compare __comp) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __set_union;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+// optional<_ForwardOutIterator>
+// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+// _ForwardOutIterator __result,
+// _Compare __comp) const noexcept;
+
template <class _Backend, class _ExecutionPolicy>
struct __sort;
// template <class _Policy, class _RandomAccessIterator, class _Comp>
diff --git a/libcxx/include/__pstl/backends/serial.h b/libcxx/include/__pstl/backends/serial.h
index c06e4d31ff3cba..294927cbb70276 100644
--- a/libcxx/include/__pstl/backends/serial.h
+++ b/libcxx/include/__pstl/backends/serial.h
@@ -13,6 +13,7 @@
#include <__algorithm/find_end.h>
#include <__algorithm/find_if.h>
#include <__algorithm/for_each.h>
+#include <__algorithm/includes.h>
#include <__algorithm/is_heap_until.h>
#include <__algorithm/merge.h>
#include <__algorithm/min_element.h>
@@ -21,6 +22,10 @@
#include <__algorithm/reverse.h>
#include <__algorithm/search.h>
#include <__algorithm/search_n.h>
+#include <__algorithm/set_
diff erence.h>
+#include <__algorithm/set_intersection.h>
+#include <__algorithm/set_symmetric_
diff erence.h>
+#include <__algorithm/set_union.h>
#include <__algorithm/stable_sort.h>
#include <__algorithm/swap_ranges.h>
#include <__algorithm/transform.h>
@@ -313,6 +318,105 @@ struct __uninitialized_move<__serial_backend_tag, _ExecutionPolicy> {
}
};
+template <class _ExecutionPolicy>
+struct __includes<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Compare>
+ optional<bool>
+ operator()(_Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _Compare __comp) const noexcept {
+ return std::includes(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__comp));
+ }
+};
+
+template <class _ExecutionPolicy>
+struct __set_
diff erence<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+ optional<_ForwardOutIterator> operator()(
+ _Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) const noexcept {
+ return std::set_
diff erence(
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+ }
+};
+
+template <class _ExecutionPolicy>
+struct __set_symmetric_
diff erence<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+ optional<_ForwardOutIterator> operator()(
+ _Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) const noexcept {
+ return std::set_symmetric_
diff erence(
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+ }
+};
+
+template <class _ExecutionPolicy>
+struct __set_union<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+ optional<_ForwardOutIterator> operator()(
+ _Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) const noexcept {
+ return std::set_union(
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+ }
+};
+
+template <class _ExecutionPolicy>
+struct __set_intersection<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Compare>
+ optional<_ForwardOutIterator> operator()(
+ _Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _ForwardOutIterator __result,
+ _Compare __comp) const noexcept {
+ return std::set_intersection(
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::move(__comp));
+ }
+};
+
} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
index d99869ce73f103..7a006be5af72b1 100644
--- a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
@@ -152,6 +152,12 @@ void f(non_forward_iterator non_fwd,
(void)std::reverse_copy(pol, it, it, non_fwd); // expected-error@*:* {{static assertion failed: reverse_copy}}
}
+ {
+ (void)std::includes(pol, non_fwd, non_fwd, it, it); // expected-error@*:* {{static assertion failed: includes}}
+ (void)std::includes(
+ pol, it, it, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: includes}}
+ }
+
{
(void)std::is_partitioned(
pol, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: is_partitioned}}
@@ -269,6 +275,69 @@ void f(non_forward_iterator non_fwd,
(void)std::search_n(pol, non_fwd, non_fwd, 1, 1, pred); // expected-error@*:* {{static assertion failed: search_n}}
}
+ {
+ (void)std::set_
diff erence(
+ pol, non_fwd, non_fwd, it, it, it); // expected-error@*:* {{static assertion failed: set_
diff erence}}
+ (void)std::set_
diff erence(
+ pol, it, it, non_fwd, non_fwd, it); // expected-error@*:* {{static assertion failed: set_
diff erence}}
+ (void)std::set_
diff erence(
+ pol, it, it, it, it, non_output); // expected-error@*:* {{static assertion failed: set_
diff erence}}
+
+ (void)std::set_
diff erence(
+ pol, non_fwd, non_fwd, it, it, it, pred); // expected-error@*:* {{static assertion failed: set_
diff erence}}
+ (void)std::set_
diff erence(
+ pol, it, it, non_fwd, non_fwd, it, pred); // expected-error@*:* {{static assertion failed: set_
diff erence}}
+ (void)std::set_
diff erence(
+ pol, it, it, it, it, non_output, pred); // expected-error@*:* {{static assertion failed: set_
diff erence}}
+ }
+
+ {
+ // expected-error@*:* {{static assertion failed: set_symmetric_
diff erence}}
+ (void)std::set_symmetric_
diff erence(pol, non_fwd, non_fwd, it, it, it);
+ // expected-error@*:* {{static assertion failed: set_symmetric_
diff erence}}
+ (void)std::set_symmetric_
diff erence(pol, it, it, non_fwd, non_fwd, it);
+ // expected-error@*:* {{static assertion failed: set_symmetric_
diff erence}}
+ (void)std::set_symmetric_
diff erence(pol, it, it, it, it, non_output);
+
+ // expected-error@*:* {{static assertion failed: set_symmetric_
diff erence}}
+ (void)std::set_symmetric_
diff erence(pol, non_fwd, non_fwd, it, it, it, pred);
+ // expected-error@*:* {{static assertion failed: set_symmetric_
diff erence}}
+ (void)std::set_symmetric_
diff erence(pol, it, it, non_fwd, non_fwd, it, pred);
+ // expected-error@*:* {{static assertion failed: set_symmetric_
diff erence}}
+ (void)std::set_symmetric_
diff erence(pol, it, it, it, it, non_output, pred);
+ }
+
+ {
+ (void)std::set_intersection(
+ pol, non_fwd, non_fwd, it, it, it); // expected-error@*:* {{static assertion failed: set_intersection}}
+ (void)std::set_intersection(
+ pol, it, it, non_fwd, non_fwd, it); // expected-error@*:* {{static assertion failed: set_intersection}}
+ (void)std::set_intersection(
+ pol, it, it, it, it, non_output); // expected-error@*:* {{static assertion failed: set_intersection}}
+
+ (void)std::set_intersection(
+ pol, non_fwd, non_fwd, it, it, it, pred); // expected-error@*:* {{static assertion failed: set_intersection}}
+ (void)std::set_intersection(
+ pol, it, it, non_fwd, non_fwd, it, pred); // expected-error@*:* {{static assertion failed: set_intersection}}
+ (void)std::set_intersection(
+ pol, it, it, it, it, non_output, pred); // expected-error@*:* {{static assertion failed: set_intersection}}
+ }
+
+ {
+ (void)std::set_union(
+ pol, non_fwd, non_fwd, it, it, it); // expected-error@*:* {{static assertion failed: set_union}}
+ (void)std::set_union(
+ pol, it, it, non_fwd, non_fwd, it); // expected-error@*:* {{static assertion failed: set_union}}
+ (void)std::set_union(pol, it, it, it, it, non_output); // expected-error@*:* {{static assertion failed: set_union}}
+
+ (void)std::set_union(
+ pol, non_fwd, non_fwd, it, it, it, pred); // expected-error@*:* {{static assertion failed: set_union}}
+ (void)std::set_union(
+ pol, it, it, non_fwd, non_fwd, it, pred); // expected-error@*:* {{static assertion failed: set_union}}
+ (void)std::set_union(
+ pol, it, it, it, it, non_output, pred); // expected-error@*:* {{static assertion failed: set_union}}
+ }
+
{
(void)std::sort(pol, non_fwd, non_fwd); // expected-error@*:* {{static assertion failed: sort}}
(void)std::sort(pol, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: sort}}
diff --git a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
index f36f12a135fbaf..03e324e502a4df 100644
--- a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
@@ -56,6 +56,10 @@ void test() {
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::find_first_of(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b), pred2);
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::includes(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::includes(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b), pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::is_heap(std::execution::par, std::begin(a), std::end(a));
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::is_heap(std::execution::par, std::begin(a), std::end(a), pred2);
@@ -115,4 +119,24 @@ void test() {
std::search_n(std::execution::par, std::begin(a), std::end(a), 1, 1);
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::search_n(std::execution::par, std::begin(a), std::end(a), 1, 1, pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_
diff erence(std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_
diff erence(
+ std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b), pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_symmetric_
diff erence(
+ std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_symmetric_
diff erence(
+ std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b), pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_intersection(std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_intersection(
+ std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b), pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_union(std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::set_union(std::execution::par, std::begin(a), std::end(a), std::begin(a), std::end(a), std::begin(b), pred2);
}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes.pass.cpp
new file mode 100644
index 00000000000000..1c6e339e0179ed
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes.pass.cpp
@@ -0,0 +1,127 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2>
+// bool
+// includes(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+EXECUTION_POLICY_SFINAE_TEST(includes);
+
+static_assert(sfinae_test_includes<int, int*, int*, int*, int*>);
+static_assert(!sfinae_test_includes<std::execution::parallel_policy, int*, int*, int*, int*>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ { // Check the return type
+ int a[] = {1};
+ auto res =
+ std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(a)), Iter2(std::end(a)));
+ static_assert(std::is_same_v<decltype(res), bool>);
+ }
+ { // Both ranges are empty
+ int a[] = {1};
+ int b[] = {1};
+ assert(std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::begin(a)), Iter2(std::begin(b)), Iter2(std::begin(b))));
+ }
+ { // Empty haystack, non-empty needly
+ int a[] = {1};
+ int b[] = {1};
+ assert(
+ !std::includes(policy, Iter1(std::begin(a)), Iter1(std::begin(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Non-empty haystack, empty needle
+ int a[] = {1};
+ int b[] = {1};
+ assert(
+ std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::begin(b))));
+ }
+ { // Haystack and needle are the same
+ int a[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+ assert(std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(a)), Iter2(std::end(a))));
+ }
+ { // Needle is a sparse subset
+ int a[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+ int b[] = {2, 4};
+ assert(std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Superset is not included in its subset
+ int a[] = {2, 4};
+ int b[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+ assert(
+ !std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Haystack and needle are equal
+ int a[] = {1, 2};
+ int b[] = {1, 2};
+ assert(std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Partial overlap
+ int a[] = {1, 2};
+ int b[] = {2, 4};
+ assert(
+ !std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Needle is one element present multiple times
+ int a[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+ int b[] = {3};
+ assert(std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Needle is two-element present multiple times
+ int a[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+ int b[] = {3, 3};
+ assert(std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Needle is three-element duplicate present once
+ int a[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+ int b[] = {3, 3, 3};
+ assert(std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ { // Needle is three-element duplicate not present
+ int a[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+ int b[] = {3, 3, 3, 3};
+ assert(
+ !std::includes(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))));
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const int*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const int*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes_comp.pass.cpp
new file mode 100644
index 00000000000000..742c3c7aa1ef35
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes_comp.pass.cpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Comp>
+// bool
+// includes(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// Comp compare);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+EXECUTION_POLICY_SFINAE_TEST(includes);
+
+static_assert(sfinae_test_includes<int, int*, int*, int*, int*, bool (*)(int, int)>);
+static_assert(!sfinae_test_includes<std::execution::parallel_policy, int*, int*, int*, int*, bool (*)(int, int)>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ { // Check the return type
+ int a[] = {1};
+ auto res = std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(a)), Iter2(std::end(a)), std::greater{});
+ static_assert(std::is_same_v<decltype(res), bool>);
+ }
+ { // Both ranges are empty
+ int a[] = {1};
+ int b[] = {1};
+ assert(std::includes(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::begin(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::begin(b)),
+ std::greater{}));
+ }
+ { // Empty haystack, non-empty needly
+ int a[] = {1};
+ int b[] = {1};
+ assert(!std::includes(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::begin(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::greater{}));
+ }
+ { // Non-empty haystack, empty needle
+ int a[] = {1};
+ int b[] = {1};
+ assert(std::includes(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::begin(b)),
+ std::greater{}));
+ }
+ { // Haystack and needle are the same
+ int a[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
+ assert(std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(a)), Iter2(std::end(a)), std::greater{}));
+ }
+ { // Needle is a sparse subset
+ int a[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
+ int b[] = {4, 2};
+ assert(std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ { // Superset is not included in its subset
+ int a[] = {4, 2};
+ int b[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
+ assert(!std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ { // Haystack and needle are equal
+ int a[] = {2, 1};
+ int b[] = {2, 1};
+ assert(std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ { // Partial overlap
+ int a[] = {2, 1};
+ int b[] = {4, 2};
+ assert(!std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ { // Needle is one element present multiple times
+ int a[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
+ int b[] = {3};
+ assert(std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ { // Needle is two-element present multiple times
+ int a[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
+ int b[] = {3, 3};
+ assert(std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ { // Needle is three-element duplicate present once
+ int a[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
+ int b[] = {3, 3, 3};
+ assert(std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ { // Needle is three-element duplicate not present
+ int a[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
+ int b[] = {3, 3, 3, 3};
+ assert(!std::includes(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::greater{}));
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const int*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const int*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.
diff erence/pstl.set_
diff erence.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.
diff erence/pstl.set_
diff erence.pass.cpp
new file mode 100644
index 00000000000000..b1a246b1fcc3ff
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.
diff erence/pstl.set_
diff erence.pass.cpp
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardOutIterator>
+// ForwardOutIterator
+// set_
diff erence(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_
diff erence);
+
+static_assert(sfinae_test_set_
diff erence<int, int*, int*, int*, int*, int*>);
+static_assert(!sfinae_test_set_
diff erence<std::execution::parallel_policy, int*, int*, int*, int*, int*>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortable;
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_
diff erence(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {11, 31};
+ T c[std::size(expected)] = {};
+ auto res = std::set_
diff erence(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {22, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_
diff erence(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const TrivialSortable*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortable*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.
diff erence/pstl.set_
diff erence_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.
diff erence/pstl.set_
diff erence_comp.pass.cpp
new file mode 100644
index 00000000000000..be55d754aae9ba
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.
diff erence/pstl.set_
diff erence_comp.pass.cpp
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
+// class ForwardOutIterator, class Compare>
+// ForwardOutIterator
+// set_
diff erence(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result,
+// Compare comp);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_
diff erence);
+
+static_assert(sfinae_test_set_
diff erence<int, int*, int*, int*, int*, int*, bool (*)(int, int)>);
+static_assert(
+ !sfinae_test_set_
diff erence<std::execution::parallel_policy, int*, int*, int*, int*, int*, bool (*)(int, int)>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortableWithComp;
+ auto comp = T::Comparator{};
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_
diff erence(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {11, 31};
+ T c[std::size(expected)] = {};
+ auto res = std::set_
diff erence(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {22, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_
diff erence(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortableWithComp*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(types::forward_iterator_list<const TrivialSortableWithComp*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection.pass.cpp
new file mode 100644
index 00000000000000..374c8e8dc59af1
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection.pass.cpp
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardOutIterator>
+// ForwardOutIterator
+// set_intersection(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_intersection);
+
+static_assert(sfinae_test_set_intersection<int, int*, int*, int*, int*, int*>);
+static_assert(!sfinae_test_set_intersection<std::execution::parallel_policy, int*, int*, int*, int*, int*>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortable;
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_intersection(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {33, 41};
+ T c[std::size(expected)] = {};
+ auto res = std::set_intersection(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {32, 42};
+ T c[std::size(expected)] = {};
+ auto res = std::set_intersection(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const TrivialSortable*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortable*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection_comp.pass.cpp
new file mode 100644
index 00000000000000..ca3e6c6d4ee8d3
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/pstl.set_intersection_comp.pass.cpp
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
+// class ForwardOutIterator, class Compare>
+// ForwardOutIterator
+// set_intersection(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result,
+// Compare comp);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_intersection);
+
+static_assert(sfinae_test_set_intersection<int, int*, int*, int*, int*, int*, bool (*)(int, int)>);
+static_assert(
+ !sfinae_test_set_intersection<std::execution::parallel_policy, int*, int*, int*, int*, int*, bool (*)(int, int)>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortableWithComp;
+ auto comp = T::Comparator{};
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_intersection(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {33, 41};
+ T c[std::size(expected)] = {};
+ auto res = std::set_intersection(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {32, 42};
+ T c[std::size(expected)] = {};
+ auto res = std::set_intersection(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortableWithComp*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(types::forward_iterator_list<const TrivialSortableWithComp*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.
diff erence/pstl.set_symmetric_
diff erence.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.
diff erence/pstl.set_symmetric_
diff erence.pass.cpp
new file mode 100644
index 00000000000000..5cec123ecc2465
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.
diff erence/pstl.set_symmetric_
diff erence.pass.cpp
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardOutIterator>
+// ForwardOutIterator
+// set_symmetric_
diff erence(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_symmetric_
diff erence);
+
+static_assert(sfinae_test_set_symmetric_
diff erence<int, int*, int*, int*, int*, int*>);
+static_assert(!sfinae_test_set_symmetric_
diff erence<std::execution::parallel_policy, int*, int*, int*, int*, int*>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortable;
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_symmetric_
diff erence(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {11, 22, 31, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_symmetric_
diff erence(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {11, 22, 31, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_symmetric_
diff erence(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const TrivialSortable*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortable*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.
diff erence/pstl.set_symmetric_
diff erence_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.
diff erence/pstl.set_symmetric_
diff erence_comp.pass.cpp
new file mode 100644
index 00000000000000..bf9410e079082b
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.
diff erence/pstl.set_symmetric_
diff erence_comp.pass.cpp
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
+// class ForwardOutIterator, class Compare>
+// ForwardOutIterator
+// set_symmetric_
diff erence(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result,
+// Compare comp);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_symmetric_
diff erence);
+
+static_assert(sfinae_test_set_symmetric_
diff erence<int, int*, int*, int*, int*, int*, bool (*)(int, int)>);
+static_assert(!sfinae_test_set_symmetric_
diff erence<
+ std::execution::parallel_policy,
+ int*,
+ int*,
+ int*,
+ int*,
+ int*,
+ bool (*)(int, int)>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortableWithComp;
+ auto comp = T::Comparator{};
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_symmetric_
diff erence(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {11, 22, 31, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_symmetric_
diff erence(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {11, 22, 31, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_symmetric_
diff erence(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortableWithComp*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(types::forward_iterator_list<const TrivialSortableWithComp*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union.pass.cpp
new file mode 100644
index 00000000000000..9fcb9584deb6ed
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union.pass.cpp
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardOutIterator>
+// ForwardOutIterator
+// set_union(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_union);
+
+static_assert(sfinae_test_set_union<int, int*, int*, int*, int*, int*>);
+static_assert(!sfinae_test_set_union<std::execution::parallel_policy, int*, int*, int*, int*, int*>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortable;
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_union(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {11, 22, 33, 31, 41, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_union(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {11, 22, 32, 31, 43, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_union(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(c));
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected)) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const TrivialSortable*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortable*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union_comp.pass.cpp
new file mode 100644
index 00000000000000..4760fbe7c2a66d
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/pstl.set_union_comp.pass.cpp
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
+// class ForwardOutIterator, class Compare>
+// ForwardOutIterator
+// set_union(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// ForwardOutIterator result,
+// Compare comp);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "../../sortable_helpers.h"
+
+EXECUTION_POLICY_SFINAE_TEST(set_union);
+
+static_assert(sfinae_test_set_union<int, int*, int*, int*, int*, int*, bool (*)(int, int)>);
+static_assert(
+ !sfinae_test_set_union<std::execution::parallel_policy, int*, int*, int*, int*, int*, bool (*)(int, int)>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ using T = TrivialSortableWithComp;
+ auto comp = T::Comparator{};
+ { // Check the result type
+ T a[] = {0};
+ T b[] = {0};
+ T c[2] = {};
+ auto res = std::set_union(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ static_assert(std::is_same_v<decltype(res), decltype(std::begin(c))>);
+ }
+ { // First is shorter
+ T a[] = {11, 33, 31, 41};
+ T b[] = {22, 32, 43, 42, 52};
+ T expected[] = {11, 22, 33, 31, 41, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_union(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ { // First is longer
+ T a[] = {22, 32, 43, 42, 52};
+ T b[] = {11, 33, 31, 41};
+ T expected[] = {11, 22, 32, 31, 43, 42, 52};
+ T c[std::size(expected)] = {};
+ auto res = std::set_union(
+ policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(b)),
+ Iter2(std::end(b)),
+ std::begin(c),
+ comp);
+ assert(res == std::end(c));
+ assert(std::lexicographical_compare(std::begin(c), res, std::begin(expected), std::end(expected), comp) == 0);
+ }
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(
+ types::forward_iterator_list<const TrivialSortableWithComp*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(types::forward_iterator_list<const TrivialSortableWithComp*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
index 64f7b396813055..ec8b60c2759d52 100644
--- a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
+++ b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
@@ -595,6 +595,109 @@ int main(int, char**) {
(void)std::swap_ranges(policy, std::move(first1), std::move(last1), std::move(first2));
});
}
+
+ {
+ auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
+
+ // includes(first1, last1, first2, last2)
+ assert_non_throwing([=, &policy] {
+ (void)std::includes(policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2));
+ });
+
+ // includes(first1, last1, first2, last2, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::includes(
+ policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), compare);
+ });
+ }
+
+ {
+ auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
+
+ // set_
diff erence(first1, last1, first2, last2, dest)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_
diff erence(
+ policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), std::move(dest));
+ });
+
+ // set_
diff erence(first1, last1, first2, last2, dest, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_
diff erence(
+ policy,
+ std::move(first1),
+ std::move(last1),
+ std::move(first2),
+ std::move(last2),
+ std::move(dest),
+ compare);
+ });
+ }
+
+ {
+ auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
+
+ // set_symmetric_
diff erence(first1, last1, first2, last2, dest)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_symmetric_
diff erence(
+ policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), std::move(dest));
+ });
+
+ // set_symmetric_
diff erence(first1, last1, first2, last2, dest, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_symmetric_
diff erence(
+ policy,
+ std::move(first1),
+ std::move(last1),
+ std::move(first2),
+ std::move(last2),
+ std::move(dest),
+ compare);
+ });
+ }
+
+ {
+ auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
+
+ // set_intersection(first1, last1, first2, last2, dest)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_intersection(
+ policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), std::move(dest));
+ });
+
+ // set_intersection(first1, last1, first2, last2, dest, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_intersection(
+ policy,
+ std::move(first1),
+ std::move(last1),
+ std::move(first2),
+ std::move(last2),
+ std::move(dest),
+ compare);
+ });
+ }
+
+ {
+ auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
+
+ // set_union(first1, last1, first2, last2, dest)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_union(
+ policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), std::move(dest));
+ });
+
+ // set_union(first1, last1, first2, last2, dest, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::set_union(
+ policy,
+ std::move(first1),
+ std::move(last1),
+ std::move(first2),
+ std::move(last2),
+ std::move(dest),
+ compare);
+ });
+ }
}
});
More information about the libcxx-commits
mailing list