[libcxx-commits] [libcxx] [libc++][pstl] Add serial implementations of set operations to PSTL (PR #233783)
Michael G. Kazakov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Oct 20 04:06:39 PDT 2026
https://github.com/mikekazakov updated https://github.com/llvm/llvm-project/pull/233783
>From 7b70cd00e8907505f3881001abd7c44232951a5c Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Tue, 20 Oct 2026 11:44:37 +0100
Subject: [PATCH 1/2] Added a serial implementation of std::includes to PSTL
---
libcxx/include/__algorithm/pstl.h | 48 ++++++
libcxx/include/__pstl/backend_fwd.h | 8 +
libcxx/include/__pstl/backends/serial.h | 16 ++
.../pstl.iterator-requirements.verify.cpp | 6 +
.../algorithms/pstl.nodiscard.verify.cpp | 4 +
.../includes/pstl.includes.pass.cpp | 127 +++++++++++++++
.../includes/pstl.includes_comp.pass.cpp | 149 ++++++++++++++++++
.../pstl.exception_handling.pass.cpp | 15 ++
8 files changed, 373 insertions(+)
create mode 100644 libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes.pass.cpp
create mode 100644 libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes_comp.pass.cpp
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index 66fa8b3cdd8a00..deb3455d5e5dfa 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -1210,6 +1210,54 @@ 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));
+}
+
_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 8bb23f352c9235..953e833e142eca 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -501,6 +501,14 @@ struct __uninitialized_fill_n;
// optional<_ForwardIterator>
// operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, const _Tp &__value) 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;
+
} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__pstl/backends/serial.h b/libcxx/include/__pstl/backends/serial.h
index c06e4d31ff3cba..827e7bf5ecaec0 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>
@@ -313,6 +314,21 @@ 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));
+ }
+};
+
} // 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..ac093a441c663f 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}}
diff --git a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
index f36f12a135fbaf..54c7ac4c0f5d75 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);
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..a7f69c4faa5922
--- /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, 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..79bddbbd2f1a05
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/pstl.includes_comp.pass.cpp
@@ -0,0 +1,149 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, ForwardIterator2, class Comp>
+// bool
+// includes(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// Comp compare);
+
+#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*, 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/pstl.exception_handling.pass.cpp b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
index 64f7b396813055..04f22c495daf5d 100644
--- a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
+++ b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
@@ -595,6 +595,21 @@ 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);
+ });
+ }
}
});
>From d3e652272b052278988a6eeafd38490288fac909 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Tue, 20 Oct 2026 12:06:25 +0100
Subject: [PATCH 2/2] Missing include
---
.../alg.set.operations/includes/pstl.includes_comp.pass.cpp | 1 +
1 file changed, 1 insertion(+)
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
index 79bddbbd2f1a05..09837fed5e7c6c 100644
--- 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
@@ -24,6 +24,7 @@
#include <cstddef>
#include <algorithm>
#include <cassert>
+#include <functional>
#include <iterator>
#include <numeric>
#include <random>
More information about the libcxx-commits
mailing list