This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
[algorithms.general]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.1 General [algorithms.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L6)
This Clause describes components that C++ programs may use to perform
algorithmic operations on <containers> and other sequences[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L10)
The following subclauses describe components for
non-modifying sequence operations,
mutating sequence operations,
sorting and related operations,
and algorithms from the C library,
as summarized in Table [85](#tab:algorithms.summary "Table 85: Algorithms library summary")[.](#2.sentence-1)
Table [85](#tab:algorithms.summary) — Algorithms library summary [[tab:algorithms.summary]](./tab:algorithms.summary)
| [🔗](#tab:algorithms.summary-row-1) | **Subclause** | **Header** |
| --- | --- | --- |
| [🔗](#tab:algorithms.summary-row-2)<br>[[algorithms.requirements]](algorithms.requirements "26.2Algorithms requirements") | Algorithms requirements | |
| [🔗](#tab:algorithms.summary-row-3)<br>[[algorithms.parallel]](algorithms.parallel "26.3Parallel algorithms") | Parallel algorithms | <execution> |
| [🔗](#tab:algorithms.summary-row-4)<br>[[algorithms.results]](algorithms.results "26.5Algorithm result types") | Algorithm result types | <algorithm> |
| [🔗](#tab:algorithms.summary-row-5)<br>[[alg.nonmodifying]](alg.nonmodifying "26.6Non-modifying sequence operations") | Non-modifying sequence operations | |
| [🔗](#tab:algorithms.summary-row-6)<br>[[alg.modifying.operations]](alg.modifying.operations "26.7Mutating sequence operations") | Mutating sequence operations | |
| [🔗](#tab:algorithms.summary-row-7)<br>[[alg.sorting]](alg.sorting "26.8Sorting and related operations") | Sorting and related operations | |
| [🔗](#tab:algorithms.summary-row-8)<br>[[numeric.ops]](numeric.ops "26.10Generalized numeric operations") | Generalized numeric operations | <numeric> |
| [🔗](#tab:algorithms.summary-row-9)<br>[[specialized.algorithms]](specialized.algorithms "26.11Specialized <memory> algorithms") | Specialized <memory> algorithms | <memory> |
| [🔗](#tab:algorithms.summary-row-10)<br>[[alg.rand]](alg.rand "26.12Specialized <random> algorithms") | Specialized <random> algorithms | <random> |
| [🔗](#tab:algorithms.summary-row-11)<br>[[alg.c.library]](alg.c.library "26.13C library algorithms") | C library algorithms | <cstdlib> |

View File

@@ -0,0 +1,609 @@
[algorithms.parallel]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [algorithms.parallel]
### [26.3.1](#defns) Preamble [[algorithms.parallel.defns]](algorithms.parallel.defns)
[1](#defns-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L287)
Subclause [algorithms.parallel] describes components that C++ programs may use
to perform operations on containers and other sequences in parallel[.](#defns-1.sentence-1)
[2](#defns-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L291)
A [*parallel algorithm*](#def:parallel_algorithm "26.3.1Preamble[algorithms.parallel.defns]") is a function template listed in this document
with a template parameter named ExecutionPolicy or constrained by the following exposition-only concept:template<class Ep>concept [*execution-policy*](#concept:execution-policy "26.3.1Preamble[algorithms.parallel.defns]") = is_execution_policy_v<remove_cvref_t<Ep>>; // *exposition only*
Such a template parameter is termed an [*execution policy template parameter*](#def:template_parameter,execution_policy "26.3.1Preamble[algorithms.parallel.defns]")[.](#defns-2.sentence-2)
[3](#defns-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L301)
A parallel algorithm accesses objects indirectly accessible via its arguments
by invoking the following functions:
- [(3.1)](#defns-3.1)
All operations of the categories of the iterators, sentinels, or mdspan types
that the algorithm is instantiated with[.](#defns-3.1.sentence-1)
- [(3.2)](#defns-3.2)
Operations on those sequence elements that are required by its specification[.](#defns-3.2.sentence-1)
- [(3.3)](#defns-3.3)
User-provided invocable objects
to be applied during the execution of the algorithm,
if required by the specification[.](#defns-3.3.sentence-1)
- [(3.4)](#defns-3.4)
Operations on those invocable objects required by the specification[.](#defns-3.4.sentence-1)
[*Note [1](#defns-note-1)*:
See [[algorithms.requirements]](algorithms.requirements "26.2Algorithms requirements")[.](#defns-3.4.sentence-2)
— *end note*]
These functions are herein called [*element access functions*](#def:element_access_functions "26.3.1Preamble[algorithms.parallel.defns]")[.](#defns-3.sentence-2)
[4](#defns-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L322)
[*Example [1](#defns-example-1)*:
The sort function may invoke the following element access functions:
- [(4.1)](#defns-4.1)
Operations of the random-access iterator of the actual template argument
(as per [[random.access.iterators]](random.access.iterators "24.3.5.7Random access iterators")),
as implied by the name of the template parameter RandomAccessIterator[.](#defns-4.1.sentence-1)
- [(4.2)](#defns-4.2)
The swap function on the elements of the sequence
(as per the preconditions specified in [[sort]](sort "26.8.2.1sort"))[.](#defns-4.2.sentence-1)
- [(4.3)](#defns-4.3)
The user-provided Compare function object[.](#defns-4.3.sentence-1)
— *end example*]
[5](#defns-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L338)
A standard library function is [*vectorization-unsafe*](#def:vectorization-unsafe "26.3.1Preamble[algorithms.parallel.defns]") if it is specified to synchronize with another function invocation, or
another function invocation is specified to synchronize with it,
and if it is not a memory allocation or deallocation function
or lock-free atomic modify-write operation ([[atomics.order]](atomics.order "32.5.4Order and consistency"))[.](#defns-5.sentence-1)
[*Note [2](#defns-note-2)*:
Implementations must ensure that internal synchronization
inside standard library functions does not prevent forward progress
when those functions are executed by threads of execution
with weakly parallel forward progress guarantees[.](#defns-5.sentence-2)
— *end note*]
[*Example [2](#defns-example-2)*: int x = 0;
std::mutex m;void f() {int a[] = {1,2};
std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); // incorrect: lock_guard constructor calls m.lock()++x; });}
The above program may result in two consecutive calls to m.lock() on the same thread of execution (which may deadlock),
because the applications of the function object are not guaranteed
to run on different threads of execution[.](#defns-5.sentence-3)
— *end example*]
### [26.3.2](#user) Requirements on user-provided function objects [[algorithms.parallel.user]](algorithms.parallel.user)
[1](#user-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L370)
Unless otherwise specified,
invocable objects passed into parallel algorithms as objects of a type
denoted by a template parameter namedPredicate,BinaryPredicate,Compare,UnaryOperation,BinaryOperation,BinaryOperation1,BinaryOperation2,BinaryDivideOp, or
constrained by a concept that subsumes [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3Concept regular_­invocable[concept.regularinvocable]") and the operators used by the analogous overloads to these parallel algorithms
that are formed by an invocation
with the specified default predicate or operation (where applicable)
shall not directly or indirectly modify objects via their arguments,
nor shall they rely on the identity of the provided objects[.](#user-1.sentence-1)
### [26.3.3](#exec) Effect of execution policies on algorithm execution [[algorithms.parallel.exec]](algorithms.parallel.exec)
[1](#exec-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L391)
An execution policy template parameter describes
the manner in which the execution of a parallel algorithm may be
parallelized and the manner in which it applies the element access functions[.](#exec-1.sentence-1)
[2](#exec-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L396)
If an object is modified by an element access function,
the algorithm will perform no other unsynchronized accesses to that object[.](#exec-2.sentence-1)
The modifying element access functions are those
which are specified as modifying the object[.](#exec-2.sentence-2)
[*Note [1](#exec-note-1)*:
For example,swap,++,--,@=, and
assignments
modify the object[.](#exec-2.sentence-3)
For the assignment and @= operators, only the left argument is modified[.](#exec-2.sentence-4)
— *end note*]
[3](#exec-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L412)
Unless otherwise stated, implementations may make arbitrary copies of elements
(with type T) from sequences
where is_trivially_copy_constructible_v<T> and is_trivially_destructible_v<T> are true[.](#exec-3.sentence-1)
[*Note [2](#exec-note-2)*:
This implies that user-supplied function objects cannot rely on
object identity of arguments for such input sequences[.](#exec-3.sentence-2)
If object identity of the arguments to these function objects
is important, a wrapping iterator
that returns a non-copied implementation object
such as reference_wrapper<T> ([[refwrap]](refwrap "22.10.6Class template reference_­wrapper")),
or some equivalent solution, can be used[.](#exec-3.sentence-3)
— *end note*]
[4](#exec-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L427)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::sequenced_policy all occur
in the calling thread of execution[.](#exec-4.sentence-1)
[*Note [3](#exec-note-3)*:
The invocations are not interleaved; see [[intro.execution]](intro.execution "6.10.1Sequential execution")[.](#exec-4.sentence-2)
— *end note*]
[5](#exec-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L435)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::unsequenced_policy are permitted to execute in an unordered fashion
in the calling thread of execution,
unsequenced with respect to one another in the calling thread of execution[.](#exec-5.sentence-1)
[*Note [4](#exec-note-4)*:
This means that multiple function object invocations
can be interleaved on a single thread of execution,
which overrides the usual guarantee from [[intro.execution]](intro.execution "6.10.1Sequential execution") that function executions do not overlap with one another[.](#exec-5.sentence-2)
— *end note*]
The behavior of a program is undefined if
it invokes a vectorization-unsafe standard library function
from user code
called from an execution::unsequenced_policy algorithm[.](#exec-5.sentence-3)
[*Note [5](#exec-note-5)*:
Because execution::unsequenced_policy allows
the execution of element access functions
to be interleaved on a single thread of execution,
blocking synchronization, including the use of mutexes, risks deadlock[.](#exec-5.sentence-4)
— *end note*]
[6](#exec-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L458)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::parallel_policy are permitted to execute either
in the invoking thread of execution or
in a thread of execution implicitly created by the library
to support parallel algorithm execution[.](#exec-6.sentence-1)
If the threads of execution created by thread ([[thread.thread.class]](thread.thread.class "32.4.3Class thread"))
or jthread ([[thread.jthread.class]](thread.jthread.class "32.4.4Class jthread"))
provide concurrent forward progress guarantees ([[intro.progress]](intro.progress "6.10.2.3Forward progress")),
then a thread of execution implicitly created by the library will provide
parallel forward progress guarantees;
otherwise, the provided forward progress guarantee isimplementation-defined[.](#exec-6.sentence-2)
Any such invocations executing in the same thread of execution
are indeterminately sequenced with respect to each other[.](#exec-6.sentence-3)
[*Note [6](#exec-note-6)*:
It is the caller's responsibility to ensure
that the invocation does not introduce data races or deadlocks[.](#exec-6.sentence-4)
— *end note*]
[*Example [1](#exec-example-1)*: int a[] = {0,1};
std::vector<int> v;
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int i) { v.push_back(i*2+1); // incorrect: data race});
The program above has a data race because of the unsynchronized access to the
container v[.](#exec-6.sentence-5)
— *end example*]
[*Example [2](#exec-example-2)*: std::atomic<int> x{0};int a[] = {1,2};
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { x.fetch_add(1, std::memory_order::relaxed); // spin wait for another iteration to change the value of xwhile (x.load(std::memory_order::relaxed) == 1) { } // incorrect: assumes execution order});
The above example depends on the order of execution of the iterations, and
will not terminate if both iterations are executed sequentially
on the same thread of execution[.](#exec-6.sentence-6)
— *end example*]
[*Example [3](#exec-example-3)*: int x = 0;
std::mutex m;int a[] = {1,2};
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); ++x;});
The above example synchronizes access to object x ensuring that it is incremented correctly[.](#exec-6.sentence-7)
— *end example*]
[7](#exec-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L518)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::parallel_unsequenced_policy are
permitted to execute
in an unordered fashion in unspecified threads of execution, and
unsequenced with respect to one another within each thread of execution[.](#exec-7.sentence-1)
These threads of execution are
either the invoking thread of execution
or threads of execution implicitly created by the library;
the latter will provide weakly parallel forward progress guarantees[.](#exec-7.sentence-2)
[*Note [7](#exec-note-7)*:
This means that multiple function object invocations can be interleaved
on a single thread of execution,
which overrides the usual guarantee from [[intro.execution]](intro.execution "6.10.1Sequential execution") that function executions do not overlap with one another[.](#exec-7.sentence-3)
— *end note*]
The behavior of a program is undefined if
it invokes a vectorization-unsafe standard library function
from user code
called from an execution::parallel_unsequenced_policy algorithm[.](#exec-7.sentence-4)
[*Note [8](#exec-note-8)*:
Because execution::parallel_unsequenced_policy allows
the execution of element access functions
to be interleaved on a single thread of execution,
blocking synchronization, including the use of mutexes, risks deadlock[.](#exec-7.sentence-5)
— *end note*]
[8](#exec-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L545)
[*Note [9](#exec-note-9)*:
The semantics of invocation withexecution::unsequenced_policy,execution::parallel_policy, orexecution::parallel_unsequenced_policy allow the implementation to fall back to sequential execution
if the system cannot parallelize an algorithm invocation,
e.g., due to lack of resources[.](#exec-8.sentence-1)
— *end note*]
[9](#exec-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L556)
If an invocation of a parallel algorithm uses threads of execution
implicitly created by the library,
then the invoking thread of execution will either
- [(9.1)](#exec-9.1)
temporarily block
with forward progress guarantee delegation ([[intro.progress]](intro.progress "6.10.2.3Forward progress"))
on the completion of these library-managed threads of execution, or
- [(9.2)](#exec-9.2)
eventually execute an element access function;
the thread of execution will continue to do so until the algorithm is finished[.](#exec-9.sentence-1)
[*Note [10](#exec-note-10)*:
In blocking with forward progress guarantee delegation in this context,
a thread of execution created by the library
is considered to have finished execution
as soon as it has finished the execution
of the particular element access function
that the invoking thread of execution logically depends on[.](#exec-9.sentence-2)
— *end note*]
[10](#exec-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L578)
The semantics of parallel algorithms invoked with an execution policy object ofimplementation-defined type
are implementation-defined[.](#exec-10.sentence-1)
### [26.3.4](#exceptions) Parallel algorithm exceptions [[algorithms.parallel.exceptions]](algorithms.parallel.exceptions)
[1](#exceptions-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L586)
During the execution of a parallel algorithm,
if temporary memory resources are required for parallelization
and none are available, the algorithm throws a bad_alloc exception[.](#exceptions-1.sentence-1)
[2](#exceptions-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L591)
During the execution of a parallel algorithm,
if the invocation of an element access function exits via an uncaught exception,
the behavior is determined by the execution policy[.](#exceptions-2.sentence-1)
### [26.3.5](#overloads) Parallel algorithm overloads [[algorithms.parallel.overloads]](algorithms.parallel.overloads)
[1](#overloads-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L598)
Parallel algorithms are algorithm overloads[.](#overloads-1.sentence-1)
Each parallel algorithm overload
has an additional function parameter P of type T&& as the first function parameter,
where T is the execution policy template parameter[.](#overloads-1.sentence-2)
[*Note [1](#overloads-note-1)*:
Not all algorithms have parallel algorithm overloads[.](#overloads-1.sentence-3)
— *end note*]
[2](#overloads-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L608)
Unless otherwise specified,
the semantics of calling a parallel algorithm overload are identical to
calling the corresponding algorithm overload without the parameter P,
using all but the first argument[.](#overloads-2.sentence-1)
[3](#overloads-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L614)
Unless otherwise specified,
the complexity requirements of a parallel algorithm overload
are relaxed from the complexity requirements of the corresponding overload
without the parameter P as follows:
when the guarantee says “at most *expr*” or
“exactly *expr*”
and does not specify the number of assignments or swaps, and*expr* is not already expressed with O() notation,
the complexity of the algorithm shall be O(expr)[.](#overloads-3.sentence-1)
[4](#overloads-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L626)
A parallel algorithm
with a template parameter named ExecutionPolicy shall not participate in overload resolution unless
that template parameter satisfies [*execution-policy*](#concept:execution-policy "26.3.1Preamble[algorithms.parallel.defns]")[.](#overloads-4.sentence-1)
### [26.3.6](#execpol) Execution policies [[execpol]](execpol)
#### [26.3.6.1](#execpol.general) General [[execpol.general]](execpol.general)
[1](#execpol.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L636)
Subclause [[execpol]](#execpol "26.3.6Execution policies") describes classes that are [*execution policy*](#def:execution_policy "26.3.6.1General[execpol.general]") types[.](#execpol.general-1.sentence-1)
An
object of an execution policy type indicates the kinds of parallelism allowed
in the execution of an algorithm and expresses the consequent requirements on
the element access functions[.](#execpol.general-1.sentence-2)
Execution policy types are declared in header [<execution>](execution.syn#header:%3cexecution%3e "33.4Header <execution> synopsis[execution.syn]")[.](#execpol.general-1.sentence-3)
[*Example [1](#execpol.general-example-1)*: using namespace std;
vector<int> v = /* ... */;
// standard sequential sort sort(v.begin(), v.end());
// explicitly sequential sort sort(execution::seq, v.begin(), v.end());
// permitting parallel execution sort(execution::par, v.begin(), v.end());
// permitting vectorization as well sort(execution::par_unseq, v.begin(), v.end()); — *end example*]
[*Note [1](#execpol.general-note-1)*:
Implementations can provide additional execution policies
to those described in this document as extensions
to address parallel architectures that require idiosyncratic
parameters for efficient execution[.](#execpol.general-1.sentence-4)
— *end note*]
#### [26.3.6.2](#execpol.type) Execution policy type trait [[execpol.type]](execpol.type)
[🔗](#lib:is_execution_policy)
`template<class T> struct is_execution_policy;
`
[1](#execpol.type-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L675)
is_execution_policy can be used to detect execution policies for the
purpose of excluding function signatures from otherwise ambiguous overload
resolution participation[.](#execpol.type-1.sentence-1)
[2](#execpol.type-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L680)
is_execution_policy<T> is a *Cpp17UnaryTypeTrait* with a
base characteristic of true_type if T is the type of a standard
or implementation-defined
execution policy, otherwise false_type[.](#execpol.type-2.sentence-1)
[*Note [1](#execpol.type-note-1)*:
This provision reserves the privilege of creating non-standard execution
policies to the library implementation[.](#execpol.type-2.sentence-2)
— *end note*]
[3](#execpol.type-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L691)
The behavior of a program that adds specializations foris_execution_policy is undefined[.](#execpol.type-3.sentence-1)
#### [26.3.6.3](#execpol.seq) Sequenced execution policy [[execpol.seq]](execpol.seq)
[🔗](#lib:execution::sequenced_policy)
`class execution::sequenced_policy { unspecified };
`
[1](#execpol.seq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L704)
The class execution::sequenced_policy is an execution policy type used
as a unique type to disambiguate parallel algorithm overloading and require
that a parallel algorithm's execution may not be parallelized[.](#execpol.seq-1.sentence-1)
[2](#execpol.seq-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L709)
During the execution of a parallel algorithm with
the execution::sequenced_policy policy,
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#execpol.seq-2.sentence-1)
#### [26.3.6.4](#execpol.par) Parallel execution policy [[execpol.par]](execpol.par)
[🔗](#lib:execution::parallel_policy)
`class execution::parallel_policy { unspecified };
`
[1](#execpol.par-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L724)
The class execution::parallel_policy is an execution policy type used as
a unique type to disambiguate parallel algorithm overloading and indicate that
a parallel algorithm's execution may be parallelized[.](#execpol.par-1.sentence-1)
[2](#execpol.par-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L729)
During the execution of a parallel algorithm with
the execution::parallel_policy policy,
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#execpol.par-2.sentence-1)
#### [26.3.6.5](#execpol.parunseq) Parallel and unsequenced execution policy [[execpol.parunseq]](execpol.parunseq)
[🔗](#lib:execution::parallel_unsequenced_policy)
`class execution::parallel_unsequenced_policy { unspecified };
`
[1](#execpol.parunseq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L744)
The class execution::parallel_unsequenced_policy is an execution policy type
used as a unique type to disambiguate parallel algorithm overloading and
indicate that a parallel algorithm's execution may be parallelized and
vectorized[.](#execpol.parunseq-1.sentence-1)
[2](#execpol.parunseq-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L750)
During the execution of a parallel algorithm with
the execution::parallel_unsequenced_policy policy,
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#execpol.parunseq-2.sentence-1)
#### [26.3.6.6](#execpol.unseq) Unsequenced execution policy [[execpol.unseq]](execpol.unseq)
[🔗](#lib:execution::unsequenced_policy)
`class execution::unsequenced_policy { unspecified };
`
[1](#execpol.unseq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L765)
The class unsequenced_policy is an execution policy type
used as a unique type to disambiguate parallel algorithm overloading and
indicate that a parallel algorithm's execution may be vectorized,
e.g., executed on a single thread using instructions
that operate on multiple data items[.](#execpol.unseq-1.sentence-1)
[2](#execpol.unseq-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L772)
During the execution of a parallel algorithm with
the execution::unsequenced_policy policy,
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#execpol.unseq-2.sentence-1)
#### [26.3.6.7](#execpol.objects) Execution policy objects [[execpol.objects]](execpol.objects)
[🔗](#lib:seq)
`inline constexpr execution::sequenced_policy execution::seq{ unspecified };
inline constexpr execution::parallel_policy execution::par{ unspecified };
inline constexpr execution::parallel_unsequenced_policy execution::par_unseq{ unspecified };
inline constexpr execution::unsequenced_policy execution::unseq{ unspecified };
`
[1](#execpol.objects-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L795)
The header [<execution>](execution.syn#header:%3cexecution%3e "33.4Header <execution> synopsis[execution.syn]") declares global objects associated with each type of execution policy[.](#execpol.objects-1.sentence-1)

View File

@@ -0,0 +1,107 @@
[algorithms.parallel.defns]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#defns)
### 26.3.1 Preamble [algorithms.parallel.defns]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L287)
Subclause [[algorithms.parallel]](algorithms.parallel "26.3Parallel algorithms") describes components that C++ programs may use
to perform operations on containers and other sequences in parallel[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L291)
A [*parallel algorithm*](#def:parallel_algorithm "26.3.1Preamble[algorithms.parallel.defns]") is a function template listed in this document
with a template parameter named ExecutionPolicy or constrained by the following exposition-only concept:template<class Ep>concept [*execution-policy*](#concept:execution-policy "26.3.1Preamble[algorithms.parallel.defns]") = is_execution_policy_v<remove_cvref_t<Ep>>; // *exposition only*
Such a template parameter is termed an [*execution policy template parameter*](#def:template_parameter,execution_policy "26.3.1Preamble[algorithms.parallel.defns]")[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L301)
A parallel algorithm accesses objects indirectly accessible via its arguments
by invoking the following functions:
- [(3.1)](#3.1)
All operations of the categories of the iterators, sentinels, or mdspan types
that the algorithm is instantiated with[.](#3.1.sentence-1)
- [(3.2)](#3.2)
Operations on those sequence elements that are required by its specification[.](#3.2.sentence-1)
- [(3.3)](#3.3)
User-provided invocable objects
to be applied during the execution of the algorithm,
if required by the specification[.](#3.3.sentence-1)
- [(3.4)](#3.4)
Operations on those invocable objects required by the specification[.](#3.4.sentence-1)
[*Note [1](#note-1)*:
See [[algorithms.requirements]](algorithms.requirements "26.2Algorithms requirements")[.](#3.4.sentence-2)
— *end note*]
These functions are herein called [*element access functions*](#def:element_access_functions "26.3.1Preamble[algorithms.parallel.defns]")[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L322)
[*Example [1](#example-1)*:
The sort function may invoke the following element access functions:
- [(4.1)](#4.1)
Operations of the random-access iterator of the actual template argument
(as per [[random.access.iterators]](random.access.iterators "24.3.5.7Random access iterators")),
as implied by the name of the template parameter RandomAccessIterator[.](#4.1.sentence-1)
- [(4.2)](#4.2)
The swap function on the elements of the sequence
(as per the preconditions specified in [[sort]](sort "26.8.2.1sort"))[.](#4.2.sentence-1)
- [(4.3)](#4.3)
The user-provided Compare function object[.](#4.3.sentence-1)
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L338)
A standard library function is [*vectorization-unsafe*](#def:vectorization-unsafe "26.3.1Preamble[algorithms.parallel.defns]") if it is specified to synchronize with another function invocation, or
another function invocation is specified to synchronize with it,
and if it is not a memory allocation or deallocation function
or lock-free atomic modify-write operation ([[atomics.order]](atomics.order "32.5.4Order and consistency"))[.](#5.sentence-1)
[*Note [2](#note-2)*:
Implementations must ensure that internal synchronization
inside standard library functions does not prevent forward progress
when those functions are executed by threads of execution
with weakly parallel forward progress guarantees[.](#5.sentence-2)
— *end note*]
[*Example [2](#example-2)*: int x = 0;
std::mutex m;void f() {int a[] = {1,2};
std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); // incorrect: lock_guard constructor calls m.lock()++x; });}
The above program may result in two consecutive calls to m.lock() on the same thread of execution (which may deadlock),
because the applications of the function object are not guaranteed
to run on different threads of execution[.](#5.sentence-3)
— *end example*]

View File

@@ -0,0 +1,23 @@
[algorithms.parallel.exceptions]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#exceptions)
### 26.3.4 Parallel algorithm exceptions [algorithms.parallel.exceptions]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L586)
During the execution of a parallel algorithm,
if temporary memory resources are required for parallelization
and none are available, the algorithm throws a bad_alloc exception[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L591)
During the execution of a parallel algorithm,
if the invocation of an element access function exits via an uncaught exception,
the behavior is determined by the execution policy[.](#2.sentence-1)

View File

@@ -0,0 +1,241 @@
[algorithms.parallel.exec]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#exec)
### 26.3.3 Effect of execution policies on algorithm execution [algorithms.parallel.exec]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L391)
An execution policy template parameter describes
the manner in which the execution of a parallel algorithm may be
parallelized and the manner in which it applies the element access functions[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L396)
If an object is modified by an element access function,
the algorithm will perform no other unsynchronized accesses to that object[.](#2.sentence-1)
The modifying element access functions are those
which are specified as modifying the object[.](#2.sentence-2)
[*Note [1](#note-1)*:
For example,swap,++,--,@=, and
assignments
modify the object[.](#2.sentence-3)
For the assignment and @= operators, only the left argument is modified[.](#2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L412)
Unless otherwise stated, implementations may make arbitrary copies of elements
(with type T) from sequences
where is_trivially_copy_constructible_v<T> and is_trivially_destructible_v<T> are true[.](#3.sentence-1)
[*Note [2](#note-2)*:
This implies that user-supplied function objects cannot rely on
object identity of arguments for such input sequences[.](#3.sentence-2)
If object identity of the arguments to these function objects
is important, a wrapping iterator
that returns a non-copied implementation object
such as reference_wrapper<T> ([[refwrap]](refwrap "22.10.6Class template reference_­wrapper")),
or some equivalent solution, can be used[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L427)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::sequenced_policy all occur
in the calling thread of execution[.](#4.sentence-1)
[*Note [3](#note-3)*:
The invocations are not interleaved; see [[intro.execution]](intro.execution "6.10.1Sequential execution")[.](#4.sentence-2)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L435)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::unsequenced_policy are permitted to execute in an unordered fashion
in the calling thread of execution,
unsequenced with respect to one another in the calling thread of execution[.](#5.sentence-1)
[*Note [4](#note-4)*:
This means that multiple function object invocations
can be interleaved on a single thread of execution,
which overrides the usual guarantee from [[intro.execution]](intro.execution "6.10.1Sequential execution") that function executions do not overlap with one another[.](#5.sentence-2)
— *end note*]
The behavior of a program is undefined if
it invokes a vectorization-unsafe standard library function
from user code
called from an execution::unsequenced_policy algorithm[.](#5.sentence-3)
[*Note [5](#note-5)*:
Because execution::unsequenced_policy allows
the execution of element access functions
to be interleaved on a single thread of execution,
blocking synchronization, including the use of mutexes, risks deadlock[.](#5.sentence-4)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L458)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::parallel_policy are permitted to execute either
in the invoking thread of execution or
in a thread of execution implicitly created by the library
to support parallel algorithm execution[.](#6.sentence-1)
If the threads of execution created by thread ([[thread.thread.class]](thread.thread.class "32.4.3Class thread"))
or jthread ([[thread.jthread.class]](thread.jthread.class "32.4.4Class jthread"))
provide concurrent forward progress guarantees ([[intro.progress]](intro.progress "6.10.2.3Forward progress")),
then a thread of execution implicitly created by the library will provide
parallel forward progress guarantees;
otherwise, the provided forward progress guarantee isimplementation-defined[.](#6.sentence-2)
Any such invocations executing in the same thread of execution
are indeterminately sequenced with respect to each other[.](#6.sentence-3)
[*Note [6](#note-6)*:
It is the caller's responsibility to ensure
that the invocation does not introduce data races or deadlocks[.](#6.sentence-4)
— *end note*]
[*Example [1](#example-1)*: int a[] = {0,1};
std::vector<int> v;
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int i) { v.push_back(i*2+1); // incorrect: data race});
The program above has a data race because of the unsynchronized access to the
container v[.](#6.sentence-5)
— *end example*]
[*Example [2](#example-2)*: std::atomic<int> x{0};int a[] = {1,2};
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { x.fetch_add(1, std::memory_order::relaxed); // spin wait for another iteration to change the value of xwhile (x.load(std::memory_order::relaxed) == 1) { } // incorrect: assumes execution order});
The above example depends on the order of execution of the iterations, and
will not terminate if both iterations are executed sequentially
on the same thread of execution[.](#6.sentence-6)
— *end example*]
[*Example [3](#example-3)*: int x = 0;
std::mutex m;int a[] = {1,2};
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); ++x;});
The above example synchronizes access to object x ensuring that it is incremented correctly[.](#6.sentence-7)
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L518)
The invocations of element access functions in parallel algorithms invoked with
an execution policy object of type execution::parallel_unsequenced_policy are
permitted to execute
in an unordered fashion in unspecified threads of execution, and
unsequenced with respect to one another within each thread of execution[.](#7.sentence-1)
These threads of execution are
either the invoking thread of execution
or threads of execution implicitly created by the library;
the latter will provide weakly parallel forward progress guarantees[.](#7.sentence-2)
[*Note [7](#note-7)*:
This means that multiple function object invocations can be interleaved
on a single thread of execution,
which overrides the usual guarantee from [[intro.execution]](intro.execution "6.10.1Sequential execution") that function executions do not overlap with one another[.](#7.sentence-3)
— *end note*]
The behavior of a program is undefined if
it invokes a vectorization-unsafe standard library function
from user code
called from an execution::parallel_unsequenced_policy algorithm[.](#7.sentence-4)
[*Note [8](#note-8)*:
Because execution::parallel_unsequenced_policy allows
the execution of element access functions
to be interleaved on a single thread of execution,
blocking synchronization, including the use of mutexes, risks deadlock[.](#7.sentence-5)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L545)
[*Note [9](#note-9)*:
The semantics of invocation withexecution::unsequenced_policy,execution::parallel_policy, orexecution::parallel_unsequenced_policy allow the implementation to fall back to sequential execution
if the system cannot parallelize an algorithm invocation,
e.g., due to lack of resources[.](#8.sentence-1)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L556)
If an invocation of a parallel algorithm uses threads of execution
implicitly created by the library,
then the invoking thread of execution will either
- [(9.1)](#9.1)
temporarily block
with forward progress guarantee delegation ([[intro.progress]](intro.progress "6.10.2.3Forward progress"))
on the completion of these library-managed threads of execution, or
- [(9.2)](#9.2)
eventually execute an element access function;
the thread of execution will continue to do so until the algorithm is finished[.](#9.sentence-1)
[*Note [10](#note-10)*:
In blocking with forward progress guarantee delegation in this context,
a thread of execution created by the library
is considered to have finished execution
as soon as it has finished the execution
of the particular element access function
that the invoking thread of execution logically depends on[.](#9.sentence-2)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L578)
The semantics of parallel algorithms invoked with an execution policy object ofimplementation-defined type
are implementation-defined[.](#10.sentence-1)

View File

@@ -0,0 +1,53 @@
[algorithms.parallel.overloads]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#overloads)
### 26.3.5 Parallel algorithm overloads [algorithms.parallel.overloads]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L598)
Parallel algorithms are algorithm overloads[.](#1.sentence-1)
Each parallel algorithm overload
has an additional function parameter P of type T&& as the first function parameter,
where T is the execution policy template parameter[.](#1.sentence-2)
[*Note [1](#note-1)*:
Not all algorithms have parallel algorithm overloads[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L608)
Unless otherwise specified,
the semantics of calling a parallel algorithm overload are identical to
calling the corresponding algorithm overload without the parameter P,
using all but the first argument[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L614)
Unless otherwise specified,
the complexity requirements of a parallel algorithm overload
are relaxed from the complexity requirements of the corresponding overload
without the parameter P as follows:
when the guarantee says “at most *expr*” or
“exactly *expr*”
and does not specify the number of assignments or swaps, and*expr* is not already expressed with O() notation,
the complexity of the algorithm shall be O(expr)[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L626)
A parallel algorithm
with a template parameter named ExecutionPolicy shall not participate in overload resolution unless
that template parameter satisfies [*execution-policy*](algorithms.parallel.defns#concept:execution-policy "26.3.1Preamble[algorithms.parallel.defns]")[.](#4.sentence-1)

View File

@@ -0,0 +1,20 @@
[algorithms.parallel.user]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#user)
### 26.3.2 Requirements on user-provided function objects [algorithms.parallel.user]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L370)
Unless otherwise specified,
invocable objects passed into parallel algorithms as objects of a type
denoted by a template parameter namedPredicate,BinaryPredicate,Compare,UnaryOperation,BinaryOperation,BinaryOperation1,BinaryOperation2,BinaryDivideOp, or
constrained by a concept that subsumes [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3Concept regular_­invocable[concept.regularinvocable]") and the operators used by the analogous overloads to these parallel algorithms
that are formed by an invocation
with the specified default predicate or operation (where applicable)
shall not directly or indirectly modify objects via their arguments,
nor shall they rely on the identity of the provided objects[.](#1.sentence-1)

View File

@@ -0,0 +1,271 @@
[algorithms.requirements]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.2 Algorithms requirements [algorithms.requirements]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L32)
All of the algorithms
are separated from the particular implementations of data structures and
are parameterized by iterator types[.](#1.sentence-1)
Because of this, they can work with program-defined data structures,
as long as these data structures have iterator types
satisfying the assumptions on the algorithms[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L40)
The entities defined in the std::ranges namespace in this Clause and
specified as function templates are
algorithm function objects ([[alg.func.obj]](alg.func.obj "16.3.3.4Algorithm function objects"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L45)
For purposes of determining the existence of data races,
algorithms shall not modify objects referenced through an iterator argument
unless the specification requires such modification[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L50)
Throughout this Clause, where the template parameters are not constrained,
the names of template parameters are used to express type requirements[.](#4.sentence-1)
- [(4.1)](#4.1)
If an algorithm's *Effects* element specifies
that a value pointed to by any iterator passed as an argument is modified,
then the type of that argument shall meet
the requirements of a mutable iterator ([[iterator.requirements]](iterator.requirements "24.3Iterator requirements"))[.](#4.1.sentence-1)
- [(4.2)](#4.2)
If an algorithm's template parameter is named InputIterator, InputIterator1, or InputIterator2,
the template argument shall meet the [*Cpp17InputIterator*](input.iterators#:Cpp17InputIterator "24.3.5.3Input iterators[input.iterators]") requirements ([[input.iterators]](input.iterators "24.3.5.3Input iterators"))[.](#4.2.sentence-1)
- [(4.3)](#4.3)
If an algorithm's template parameter is named OutputIterator, OutputIterator1, or OutputIterator2,
the template argument shall meet the [*Cpp17OutputIterator*](output.iterators#:Cpp17OutputIterator "24.3.5.4Output iterators[output.iterators]") requirements ([[output.iterators]](output.iterators "24.3.5.4Output iterators"))[.](#4.3.sentence-1)
- [(4.4)](#4.4)
If an algorithm's template parameter is named ForwardIterator, ForwardIterator1, ForwardIterator2, or NoThrowForwardIterator,
the template argument shall meet the [*Cpp17ForwardIterator*](forward.iterators#:Cpp17ForwardIterator "24.3.5.5Forward iterators[forward.iterators]") requirements ([[forward.iterators]](forward.iterators "24.3.5.5Forward iterators"))
if it is required to be a mutable iterator, or
model [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11Concept forward_­iterator[iterator.concept.forward]") ([[iterator.concept.forward]](iterator.concept.forward "24.3.4.11Concept forward_­iterator")) otherwise[.](#4.4.sentence-1)
- [(4.5)](#4.5)
If an algorithm's template parameter is named NoThrowForwardIterator,
the template argument
is also required to have the property that no exceptions are thrown
from increment, assignment, or comparison of, or
indirection through, valid iterators[.](#4.5.sentence-1)
- [(4.6)](#4.6)
If an algorithm's template parameter is named BidirectionalIterator, BidirectionalIterator1, or BidirectionalIterator2,
the template argument shall meet the [*Cpp17BidirectionalIterator*](bidirectional.iterators#:Cpp17BidirectionalIterator "24.3.5.6Bidirectional iterators[bidirectional.iterators]") requirements ([[bidirectional.iterators]](bidirectional.iterators "24.3.5.6Bidirectional iterators"))
if it is required to be a mutable iterator, or model [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12Concept bidirectional_­iterator[iterator.concept.bidir]") ([[iterator.concept.bidir]](iterator.concept.bidir "24.3.4.12Concept bidirectional_­iterator")) otherwise[.](#4.6.sentence-1)
- [(4.7)](#4.7)
If an algorithm's template parameter is named RandomAccessIterator, RandomAccessIterator1, or RandomAccessIterator2,
the template argument shall meet the [*Cpp17RandomAccessIterator*](random.access.iterators#:Cpp17RandomAccessIterator "24.3.5.7Random access iterators[random.access.iterators]") requirements ([[random.access.iterators]](random.access.iterators "24.3.5.7Random access iterators"))
if it is required to be a mutable iterator, or model [random_access_iterator](iterator.concept.random.access#concept:random_access_iterator "24.3.4.13Concept random_­access_­iterator[iterator.concept.random.access]") ([[iterator.concept.random.access]](iterator.concept.random.access "24.3.4.13Concept random_­access_­iterator")) otherwise[.](#4.7.sentence-1)
[*Note [1](#note-1)*:
These requirements do not affect iterator arguments that are constrained,
for which iterator category and mutability requirements
are expressed explicitly[.](#4.sentence-2)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L115)
Both in-place and copying versions are provided for certain algorithms[.](#5.sentence-1)[200](#footnote-200 "The decision whether to include a copying version was usually based on complexity considerations. When the cost of doing the operation dominates the cost of copy, the copying version is not included. For example, sort_­copy is not included because the cost of sorting is much more significant, and users can invoke copy followed by sort.")
When such a version is provided for *algorithm* it is called*algorithm_copy*[.](#5.sentence-2)
Algorithms that take predicates end with the suffix _if (which follows the suffix _copy)[.](#5.sentence-3)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L131)
When not otherwise constrained, the Predicate parameter is used
whenever an algorithm expects a function object ([[function.objects]](function.objects "22.10Function objects")) that,
when applied to the result of dereferencing the corresponding iterator,
returns a value testable as true[.](#6.sentence-1)
If an algorithm takes Predicate pred as its argument andfirst as its iterator argument with value type T,
the expression pred(*first) shall be well-formed and
the type decltype(pred(*first)) shall model[*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]") ([[concept.booleantestable]](concept.booleantestable "18.5.2Boolean testability"))[.](#6.sentence-2)
The function object pred shall not apply any non-constant function
through its argument[.](#6.sentence-3)
Given a glvalue u of type (possibly const) T that designates the same object as *first,pred(u) shall be a valid expression
that is equal to pred(*first)[.](#6.sentence-4)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L148)
When not otherwise constrained, the BinaryPredicate parameter is used
whenever an algorithm expects a function object that, when applied
to the result of dereferencing two corresponding iterators or
to dereferencing an iterator and type T when T is part of the signature,
returns a value testable as true[.](#7.sentence-1)
If an algorithm takes BinaryPredicate binary_pred as its argument andfirst1 and first2 as its iterator arguments
with respective value types T1 and T2,
the expression binary_pred(*first1, *first2) shall be well-formed and
the type decltype(binary_pred(*first1, *first2)) shall model[*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]")[.](#7.sentence-2)
Unless otherwise specified,BinaryPredicate always takes the first iterator's value_type as its first argument, that is, in those cases when T value is part of the signature,
the expression binary_pred(*first1, value) shall be well-formed and
the type decltype(binary_pred(*first1, value)) shall model[*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]")[.](#7.sentence-3)
binary_pred shall not apply any non-constant function
through any of its arguments[.](#7.sentence-4)
Given a glvalue u of type (possibly const) T1 that designates the same object as *first1, and
a glvalue v of type (possibly const) T2 that designates the same object as *first2,binary_pred(u, *first2),binary_pred(*first1, v), andbinary_pred(u, v) shall each be a valid expression that is equal tobinary_pred(*first1, *first2), andbinary_pred(u, value) shall be a valid expression that is equal tobinary_pred(*first1, value)[.](#7.sentence-5)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L183)
The parametersUnaryOperation,BinaryOperation,BinaryOperation1,
and BinaryOperation2 are used
whenever an algorithm expects a function object ([[function.objects]](function.objects "22.10Function objects"))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L192)
[*Note [2](#note-2)*:
Unless otherwise specified, algorithms that take function objects as arguments
can copy those function objects freely[.](#9.sentence-1)
If object identity is important,
a wrapper class that points to a non-copied implementation object
such as reference_wrapper<T> ([[refwrap]](refwrap "22.10.6Class template reference_­wrapper")), or some equivalent solution,
can be used[.](#9.sentence-2)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L202)
When the description of an algorithm gives an expression such as*first == value for a condition, the expression
shall evaluate to either true or false in boolean contexts[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L207)
In the description of the algorithms, operator + is used for some of the iterator categories
for which it does not have to be defined[.](#11.sentence-1)
In these cases the semantics of a + n are the same as those ofauto tmp = a;for (; n < 0; ++n) --tmp;for (; n > 0; --n) ++tmp;return tmp;
Similarly, operator - is used
for some combinations of iterators and sentinel types
for which it does not have to be defined[.](#11.sentence-3)
If [a, b) denotes a range,
the semantics of b - a in these cases are the same as those ofiter_difference_t<decltype(a)> n = 0;for (auto tmp = a; tmp != b; ++tmp) ++n;return n; and if [b, a) denotes a range, the same as those ofiter_difference_t<decltype(b)> n = 0;for (auto tmp = b; tmp != a; ++tmp) --n;return n;
For each iterator i and sentinel s produced from a range r,
the semantics of s - i has the same type, value, and value category
as ranges::distance(i, s)[.](#11.sentence-5)
[*Note [3](#note-3)*:
The implementation can use ranges::distance(r) when that produces the same value as ranges::distance(i, s)[.](#11.sentence-6)
This can be more efficient for sized ranges[.](#11.sentence-7)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L244)
In the description of the algorithms,
given an iterator a whose difference type is D, and
an expression n of integer-like type other than cv D,
the semantics of a + n and a - n are, respectively,
those of a + D(n) and a - D(n)[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L251)
In the description of algorithm return values,
a sentinel value s denoting the end of a range [i, s)
is sometimes returned where an iterator is expected[.](#13.sentence-1)
In these cases,
the semantics are as if the sentinel is converted into an iterator usingranges::next(i, s)[.](#13.sentence-2)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L259)
Overloads of algorithms that take [range](range.range#concept:range "25.4.2Ranges[range.range]") arguments ([[range.range]](range.range "25.4.2Ranges"))
behave as if they are implemented by
dispatching to the overload in namespace ranges that takes separate iterator and sentinel arguments,
where for each range argument r
- [(14.1)](#14.1)
a corresponding iterator argument is initialized with ranges::begin(r) and
- [(14.2)](#14.2)
a corresponding sentinel argument is initialized with ranges::end(r),
or ranges::next(ranges::begin(r), ranges::end(r)) if the type of r models [forward_range](range.refinements#concept:forward_range "25.4.6Other range refinements[range.refinements]") and computing ranges::next meets the specified complexity requirements[.](#14.sentence-1)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L275)
The well-formedness and behavior of a call to an algorithm with
an explicitly-specified template argument list
is unspecified, except where explicitly stated otherwise[.](#15.sentence-1)
[*Note [4](#note-4)*:
Consequently, an implementation can declare an algorithm with
different template parameters than those presented[.](#15.sentence-2)
— *end note*]
[200)](#footnote-200)[200)](#footnoteref-200)
The decision whether to include a copying version was
usually based on complexity considerations[.](#footnote-200.sentence-1)
When the cost of doing the operation dominates the cost of copy,
the copying version is not included[.](#footnote-200.sentence-2)
For example, sort_copy is not included
because the cost of sorting is much more significant,
and users can invoke copy followed by sort[.](#footnote-200.sentence-3)

File diff suppressed because one or more lines are too long