Significant changes to P0202R2 are marked with blue.
Show deleted lines.
The Standard Library provides a great collection of algorithms, many of which currently lack constexpr support.
Even a simple constexpr usage requires reimplementing a big bunch of the Standard Library. Consider the simple example:
#include#include int main() { // OK constexpr std::array a { 'H', 'e', 'l', 'l', 'o' }; // Failures: // * std::find is not constexpr constexpr auto it = std::find(a.rbegin(), a.rend(), 'H'); }
This proposal concentrates on constexpr algorithms, deferring simple containers and iterators to a separate proposal.
A proof of concept implementation for some algorithms, is available at: rhalbersma and Boost.Algorithm.
This proposal is a pure library extension. It proposes changes to
existing headers and such that the changes do not break existing code
and do not degrade performance. It does not require any changes in the core
language in simple cases of non assembly optimized Standard Library, and it could be implemented in standard C++.
Depending on the Standard Library implementation this proposal may rely on P0031R0.
P0031R0 was adopted.
P0031R0 provides constexpr additions to std::advance, std::distance, std::move_iterator
and other functions and classes. Those may be used by some implementations of header.
must not have constexpr additionsExisting implementations of the functions in header usually rely on functions from .
For example std::copy usually takes advantage of std::memmove for POD types.
During the Jacksonville meeting it was decided not to modify the
headers, leading to a decision to use compiler specific intrinsics instead of functions from header.
This proposal assumes that:
constexpr by compiler vendors.constexpr compiler intrinsic.constexpr or could be replaced with intrinsics. implementations.libstdc++ and libc++ implement differently. libc++ uses some functions from header,
libstdc++ uses compiler specific intrinsics:
| libstdc++ | libc++ | Some of the Algorithms |
| __builtin_memmove | std::memmove | copy, sort, partition, copy_backward |
| __builtin_memset | std::memset | fill, fill_n |
| __builtin_memcmp | equal, lexicographical_compare |
GCC's intrinsic __builtin_memcmp is already usable in constant expressions; intrinsics __builtin_memmove, __builtin_memset
could be probably easily tuned to be usable in constant expressions.
libc++ will probably have to follow the GCC steps and use intrinsics for
std::memmove,
std::memset or just remove their usage and rely on compiler's optimizations.
Algorithms stable_partition, inplace_merge and stable_sort allocate memory, construct variables using
placement new, use unique_ptr and do other things not
acceptable in constexpr expressions. Making those algorithms constexpr
seems to be a hard task that would
require a lot of intrinsics. Those algorithms are not marked with
constexpr in this wording.
Algorithms shuffle and sample rely upon uniform_int_distribution that has no constexpr functions.
Those algorithms are not marked with constexpr in this wording.
libc++ uses goto in some algorithms, this must be pretty simple to fix without affecting performance.
ExecutionPolicy&& overloads with constexpr.It seems that N4687 accidentaly marks some of the ExecutionPolicy&& overloads with constexpr execution policy.
This wording does not mark the ExecutionPolicy&& overloads with constexpr.
std::swap with constexpr.During the LWG discussion it was noted that Core Issue 1581
affects is_swappable and swap. This paper avoids marking with constexpr the swap function and all the algorithms that
have ValueSwappable requirement(20.5.3.2) are also not marked.
Adding constexpr to algorithms that use swap, numeric algorithms, searchers, some of the functions in char_traits
and functions that relay on constexpr algorithms (like std::arrays comparison operators) will be covered in separate papers.
All the additions to the Standard are marked with underlined green.
Note for editor: All the functions in [algorithms.general] must be marked with constexpr, except functions
shuffle, sample, stable_sort, stable_partition, inplace_merge, functions accepting ExecutionPolicy
and algorithms that have ValueSwappable requirement(20.5.3.2):
swap_rangesiter_swapreverserotateshufflesortstable_sortpartial_sortpartial_sort_copynth_elementpartitionstable_partitioninplace_mergepush_heappop_heapmake_heapsort_heapnext_permutationprev_permutation#includenamespace std { // 28.5, non-modifying sequence operations: // 28.5.1, all of template constexpr bool all_of(InputIterator first, InputIterator last, Predicate pred); template bool all_of(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); // 28.5.2, any of template constexpr bool any_of(InputIterator first, InputIterator last, Predicate pred); template bool any_of(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); // 28.5.3, none of template constexpr bool none_of(InputIterator first, InputIterator last, Predicate pred); template bool none_of(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); // 28.5.4, for each template constexpr Function for_each(InputIterator first, InputIterator last, Function f); template void for_each(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Function f); template constexpr InputIterator for_each_n(InputIterator first, Size n, Function f); template ForwardIterator for_each_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, Function f); // 28.5.5, find template constexpr InputIterator find(InputIterator first, InputIterator last, const T& value); template ForwardIterator find(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, const T& value); template constexpr InputIterator find_if(InputIterator first, InputIterator last, Predicate pred); template ForwardIterator find_if(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); template constexpr InputIterator find_if_not(InputIterator first, InputIterator last, Predicate pred); template ForwardIterator find_if_not(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); // 28.5.6, find end template constexpr ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template constexpr ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template ForwardIterator1 find_end(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template ForwardIterator1 find_end(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); // 28.5.7, find first template constexpr InputIterator find_first_of(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2); template constexpr InputIterator find_first_of(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2, BinaryPredicate pred); template ForwardIterator1 find_first_of(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template ForwardIterator find_first_of(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); // 28.5.8, adjacent find template constexpr ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last); template constexpr ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template ForwardIterator adjacent_find(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last); template ForwardIterator adjacent_find(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, BinaryPredicate pred); // 28.5.9, count template constexpr typename iterator_traits ::difference_type count(InputIterator first, InputIterator last, const T& value); template typename iterator_traits ::difference_type count(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, const T& value); template constexpr typename iterator_traits ::difference_type count_if(InputIterator first, InputIterator last, Predicate pred); template typename iterator_traits ::difference_type count_if(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); // 28.5.10, mismatch template constexpr pair mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); template constexpr pair mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred); template constexpr pair mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template constexpr pair mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); template pair mismatch(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template pair mismatch(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template pair mismatch(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template pair mismatch(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); // 28.5.11, equal template constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); template constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred); template constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); template bool equal(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template bool equal(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template bool equal(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template bool equal(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); // 28.5.12, is permutation template constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); // 28.5.13, search template constexpr ForwardIterator1 search( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template constexpr ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template ForwardIterator1 search( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template ForwardIterator1 search( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); template constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); template ForwardIterator search_n(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Size count, const T& value); template ForwardIterator search_n(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); template constexpr ForwardIterator search(ForwardIterator first, ForwardIterator last, const Searcher &searcher); // 28.6, modifying sequence operations: // 28.6.1, copy: template constexpr OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); template ForwardIterator2 copy(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template constexpr OutputIterator copy_n(InputIterator first, Size n, OutputIterator result); template ForwardIterator2 copy_n(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, Size n, ForwardIterator2 result); template constexpr OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); template ForwardIterator2 copy_if(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); template constexpr BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result); // 28.6.2, move template constexpr OutputIterator move(InputIterator first, InputIterator last, OutputIterator result); template ForwardIterator2 move(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template constexpr BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result); // 28.6.3, swap template constexpr ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template ForwardIterator2 swap_ranges(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template constexpr void iter_swap(ForwardIterator1 a, ForwardIterator2 b); // 28.6.4, transform template constexpr OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op); template constexpr OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op); template ForwardIterator2 transform(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, UnaryOperation op); template ForwardIterator transform(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator result, BinaryOperation binary_op); // 28.6.5, replace template constexpr void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); template void replace(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); template constexpr void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); template void replace_if(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); template constexpr OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value); template ForwardIterator2 replace_copy(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, const T& new_value); template constexpr OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value); template ForwardIterator2 replace_copy_if(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred, const T& new_value); // 28.6.6, fill template constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value); template void fill(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, const T& value); template constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); template ForwardIterator fill_n(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, Size n, const T& value); // 28.6.7, generate template constexpr void generate(ForwardIterator first, ForwardIterator last, Generator gen); template void generate(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Generator gen); template constexpr OutputIterator generate_n(OutputIterator first, Size n, Generator gen); template ForwardIterator generate_n(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, Size n, Generator gen); // 28.6.8, remove template constexpr ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); template ForwardIterator remove(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, const T& value); template constexpr ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred); template ForwardIterator remove_if(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); template constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template ForwardIterator2 remove_copy(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& value); template constexpr OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); template ForwardIterator2 remove_copy_if(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); // 28.6.9, unique template constexpr ForwardIterator unique(ForwardIterator first, ForwardIterator last); template constexpr ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template ForwardIterator unique(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last); template ForwardIterator unique(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template constexpr OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result); template constexpr OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred); template ForwardIterator2 unique_copy(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template ForwardIterator2 unique_copy(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryPredicate pred); // 28.6.10, reverse template constexpr void reverse(BidirectionalIterator first, BidirectionalIterator last); template void reverse(ExecutionPolicy&& exec, // see 28.4.5 BidirectionalIterator first, BidirectionalIterator last); template constexpr OutputIterator reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result); template ForwardIterator reverse_copy(ExecutionPolicy&& exec, // see 28.4.5 BidirectionalIterator first, BidirectionalIterator last, ForwardIterator result); // 28.6.11, rotate template constexpr ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last); template ForwardIterator rotate(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator middle, ForwardIterator last); template constexpr OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result); template ForwardIterator rotate_copy( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator middle, ForwardIterator last, ForwardIterator result); // 28.6.12, sample template SampleIterator sample(PopulationIterator first, PopulationIterator last, SampleIterator out, Distance n, UniformRandomNumberGenerator&& g); // 28.6.13, shuffle template void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& g); // 28.7.4, partitions template constexpr bool is_partitioned(InputIterator first, InputIterator last, Predicate pred); template bool is_partitioned(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); template constexpr ForwardIterator partition(ForwardIterator first, ForwardIterator last, Predicate pred); template ForwardIterator partition(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Predicate pred); template BidirectionalIterator stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); template BidirectionalIterator stable_partition(ExecutionPolicy&& exec, // see 28.4.5 BidirectionalIterator first, BidirectionalIterator last, Predicate pred); template constexpr pair partition_copy(InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred); template pair partition_copy(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, ForwardIterator1 out_true, ForwardIterator2 out_false, Predicate pred); template constexpr ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, Predicate pred); // 28.7, sorting and related operations // 28.7.1, sorting template constexpr void sort(RandomAccessIterator first, RandomAccessIterator last); template constexpr void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template void sort(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last); template void sort(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last, Compare comp); template void stable_sort(RandomAccessIterator first, RandomAccessIterator last); template void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template void stable_sort(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last); template void stable_sort(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last, Compare comp); template constexpr void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); template constexpr void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); template void partial_sort(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); template void partial_sort(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); template constexpr RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template constexpr RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp); template RandomAccessIterator partial_sort_copy( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template RandomAccessIterator partial_sort_copy( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp); template constexpr bool is_sorted(ForwardIterator first, ForwardIterator last); template constexpr bool is_sorted(ForwardIterator first, ForwardIterator last, Compare comp); template bool is_sorted(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last); template bool is_sorted(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Compare comp); template constexpr ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last); template constexpr ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last, Compare comp); template ForwardIterator is_sorted_until(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last); template ForwardIterator is_sorted_until(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Compare comp); // 28.7.2, Nth element template constexpr void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); template constexpr void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); template void nth_element(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); template void nth_element(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); // 28.7.3, binary search template constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); template constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); template constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); template constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); template constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value); template constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); template constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); template constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); // 28.7.5, merge template constexpr OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template constexpr OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template ForwardIterator merge(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator merge(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); template void inplace_merge(ExecutionPolicy&& exec, // see 28.4.5 BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template void inplace_merge(ExecutionPolicy&& exec, // see 28.4.5 BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); // 28.7.6, set operations template constexpr bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template constexpr bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp); template bool includes(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template bool includes(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); template constexpr OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template constexpr OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template ForwardIterator set_union(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator set_union(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template constexpr OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template constexpr OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template ForwardIterator set_intersection( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template OutputIterator set_intersection( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template constexpr OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template constexpr OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template ForwardIterator set_difference( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator set_difference( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template constexpr OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template constexpr OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template ForwardIterator set_symmetric_difference( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator set_symmetric_difference( ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); // 28.7.7, heap operations template constexpr void push_heap(RandomAccessIterator first, RandomAccessIterator last); template constexpr void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template constexpr void pop_heap(RandomAccessIterator first, RandomAccessIterator last); template constexpr void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template constexpr void make_heap(RandomAccessIterator first, RandomAccessIterator last); template constexpr void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template constexpr void sort_heap(RandomAccessIterator first, RandomAccessIterator last); template constexpr void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template constexpr bool is_heap(RandomAccessIterator first, RandomAccessIterator last); template constexpr bool is_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template bool is_heap(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last); template bool is_heap(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last, Compare comp); template constexpr RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last); template constexpr RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template RandomAccessIterator is_heap_until(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last); template RandomAccessIterator is_heap_until(ExecutionPolicy&& exec, // see 28.4.5 RandomAccessIterator first, RandomAccessIterator last, Compare comp); // 28.7.8, minimum and maximum template constexpr const T& min(const T& a, const T& b); template constexpr const T& min(const T& a, const T& b, Compare comp); template constexpr T min(initializer_list t); template constexpr T min(initializer_list t, Compare comp); template constexpr const T& max(const T& a, const T& b); template constexpr const T& max(const T& a, const T& b, Compare comp); template constexpr T max(initializer_list t); template constexpr T max(initializer_list t, Compare comp); template constexpr pair minmax(const T& a, const T& b); template constexpr pair minmax(const T& a, const T& b, Compare comp); template constexpr pair minmax(initializer_list t); template constexpr pair minmax(initializer_list t, Compare comp); template constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last) template constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp); template constexpr ForwardIterator min_element(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last); template constexpr ForwardIterator min_element(ExecutionPolicy&& exec, // see 28.4.5 ForwardIterator first, ForwardIterator last, Compare comp); template constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last) template constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp); template