docs/classtf_1_1FlowBuilder.html
class to build a task dependency graph
The class provides essential methods to construct a task dependency graph from which tf::Taskflow and tf::Subflow are derived.
class Subflowclass to construct a subflow graph from the execution of a dynamic task class Taskflowclass to create a taskflow object
FlowBuilder(Graph& graph)constructs a flow builder with a graph
template<typename C, std::enable_if_t<is_static_task_v<C>, void>* = nullptr>
auto emplace(C&& callable) -> Taskcreates a static task
template<typename C, std::enable_if_t<is_runtime_task_v<C>, void>* = nullptr>
auto emplace(C&& callable) -> Taskcreates a runtime task
template<typename C, std::enable_if_t<is_subflow_task_v<C>, void>* = nullptr>
auto emplace(C&& callable) -> Taskcreates a dynamic task
template<typename C, std::enable_if_t<is_condition_task_v<C>, void>* = nullptr>
auto emplace(C&& callable) -> Taskcreates a condition task
template<typename C, std::enable_if_t<is_multi_condition_task_v<C>, void>* = nullptr>
auto emplace(C&& callable) -> Taskcreates a multi-condition task
template<typename... C, std::enable_if_t<(sizeof...(C)>1), void>* = nullptr>
auto emplace(C && ... callables) -> autocreates multiple tasks from a list of callable objectsvoid erase(Task task)removes a task from a taskflow
template<typename T>
auto composed_of(T& object) -> Taskcreates a module task for the target objectauto placeholder() -> Taskcreates a placeholder taskvoid linearize(std::vector<Task>& tasks)adds adjacent dependency links to a linear list of tasksvoid linearize(std::initializer_list<Task> tasks)adds adjacent dependency links to a linear list of tasks
template<typename B, typename E, typename C, typename P = DefaultPartitioner>
auto for_each(B first, E last, C callable, P part = P()) -> Taskconstructs an STL-styled parallel-for task
template<typename B, typename E, typename S, typename C, typename P = DefaultPartitioner>
auto for_each_index(B first, E last, S step, C callable, P part = P()) -> Taskconstructs an index-based parallel-for task
template<typename R, typename C, typename P = DefaultPartitioner>
auto for_each_by_index(R range, C callable, P part = P()) -> Taskconstructs an index range-based parallel-for task
template<typename B, typename E, typename O, typename C, typename P = DefaultPartitioner, std::enable_if_t<is_partitioner_v<std::decay_t<P>>, void>* = nullptr>
auto transform(B first1, E last1, O d_first, C c, P part = P()) -> Taskconstructs a parallel-transform task
template<typename B1, typename E1, typename B2, typename O, typename C, typename P = DefaultPartitioner, std::enable_if_t<! is_partitioner_v<std::decay_t<C>>, void>* = nullptr>
auto transform(B1 first1, E1 last1, B2 first2, O d_first, C c, P part = P()) -> Taskconstructs a parallel-transform task
template<typename B, typename E, typename T, typename O, typename P = DefaultPartitioner>
auto reduce(B first, E last, T& init, O bop, P part = P()) -> Taskconstructs an STL-styled parallel-reduction task
template<typename R, typename T, typename L, typename G, typename P = DefaultPartitioner>
auto reduce_by_index(R range, T& init, L lop, G gop, P part = P()) -> Taskconstructs an index range-based parallel-reduction task
template<typename B, typename E, typename T, typename BOP, typename UOP, typename P = DefaultPartitioner, std::enable_if_t<is_partitioner_v<std::decay_t<P>>, void>* = nullptr>
auto transform_reduce(B first, E last, T& init, BOP bop, UOP uop, P part = P()) -> Taskconstructs an STL-styled parallel transform-reduce task
template<typename B1, typename E1, typename B2, typename T, typename BOP_R, typename BOP_T, typename P = DefaultPartitioner, std::enable_if_t<! is_partitioner_v<std::decay_t<BOP_T>>, void>* = nullptr>
auto transform_reduce(B1 first1, E1 last1, B2 first2, T& init, BOP_R bop_r, BOP_T bop_t, P part = P()) -> Taskconstructs an STL-styled parallel transform-reduce task
template<typename B, typename E, typename D, typename BOP>
auto inclusive_scan(B first, E last, D d_first, BOP bop) -> Taskcreates an STL-styled parallel inclusive-scan task
template<typename B, typename E, typename D, typename BOP, typename T>
auto inclusive_scan(B first, E last, D d_first, BOP bop, T init) -> Taskcreates an STL-styled parallel inclusive-scan task with an initial value
template<typename B, typename E, typename D, typename T, typename BOP>
auto exclusive_scan(B first, E last, D d_first, T init, BOP bop) -> Taskcreates an STL-styled parallel exclusive-scan task
template<typename B, typename E, typename D, typename BOP, typename UOP>
auto transform_inclusive_scan(B first, E last, D d_first, BOP bop, UOP uop) -> Taskcreates an STL-styled parallel transform-inclusive scan task
template<typename B, typename E, typename D, typename BOP, typename UOP, typename T>
auto transform_inclusive_scan(B first, E last, D d_first, BOP bop, UOP uop, T init) -> Taskcreates an STL-styled parallel transform-inclusive scan task
template<typename B, typename E, typename D, typename T, typename BOP, typename UOP>
auto transform_exclusive_scan(B first, E last, D d_first, T init, BOP bop, UOP uop) -> Taskcreates an STL-styled parallel transform-exclusive scan task
template<typename B, typename E, typename T, typename UOP, typename P = DefaultPartitioner>
auto find_if(B first, E last, T& result, UOP predicate, P part = P()) -> Taskconstructs a task to perform STL-styled find-if algorithm
template<typename B, typename E, typename T, typename UOP, typename P = DefaultPartitioner>
auto find_if_not(B first, E last, T& result, UOP predicate, P part = P()) -> Taskconstructs a task to perform STL-styled find-if-not algorithm
template<typename B, typename E, typename T, typename C, typename P>
auto min_element(B first, E last, T& result, C comp, P part) -> Taskconstructs a task to perform STL-styled min-element algorithm
template<typename B, typename E, typename T, typename C, typename P>
auto max_element(B first, E last, T& result, C comp, P part) -> Taskconstructs a task to perform STL-styled max-element algorithm
template<typename B, typename E, typename C>
auto sort(B first, E last, C cmp) -> Taskconstructs a dynamic task to perform STL-styled parallel sort
template<typename B, typename E>
auto sort(B first, E last) -> Taskconstructs a dynamic task to perform STL-styled parallel sort using the std::less<T> comparator, where T is the element type
Graph& _graphassociated graph object
creates a static task
| Template parameters |
|---|
| C |
| Parameters |
| --- |
| callable |
| Returns |
The following example creates a static task.
tf::Task static\_task = taskflow.emplace([](){});
creates a runtime task
| Template parameters |
|---|
| C |
| Parameters |
| --- |
| callable |
| Returns |
The following example creates a runtime task.
tf::Task static\_task = taskflow.emplace([](tf::Runtime&){});
creates a dynamic task
| Template parameters |
|---|
| C |
| Parameters |
| --- |
| callable |
| Returns |
The following example creates a dynamic task (tf::Subflow) that spawns two static tasks.
tf::Task dynamic\_task = taskflow.emplace([](tf::Subflow& sf){tf::Task static\_task1 = sf.emplace([](){});tf::Task static\_task2 = sf.emplace([](){});});
creates a condition task
| Template parameters |
|---|
| C |
| Parameters |
| --- |
| callable |
| Returns |
The following example creates an if-else block using one condition task and three static tasks.
tf::Taskflow taskflow;auto [init, cond, yes, no] = taskflow.emplace([] () { },[] () { return 0; },[] () { std::cout \<\< "yes\n"; },[] () { std::cout \<\< "no\n"; });// executes yes if cond returns 0, or no if cond returns 1cond.precede(yes, no);cond.succeed(init);
creates a multi-condition task
| Template parameters |
|---|
| C |
| Parameters |
| --- |
| callable |
| Returns |
The following example creates a multi-condition task that selectively jumps to two successor tasks.
tf::Taskflow taskflow;auto [init, cond, branch1, branch2, branch3] = taskflow.emplace([] () { },[] () { return tf::SmallVector{0, 2}; },[] () { std::cout \<\< "branch1\n"; },[] () { std::cout \<\< "branch2\n"; },[] () { std::cout \<\< "branch3\n"; });// executes branch1 and branch3 when cond returns 0 and 2cond.precede(branch1, branch2, branch3);cond.succeed(init);
creates multiple tasks from a list of callable objects
| Template parameters |
|---|
| C |
| Parameters |
| --- |
| callables |
| Returns |
The method returns a tuple of tasks each corresponding to the given callable target. You can use structured binding to get the return tasks one by one. The following example creates four static tasks and assign them to A, B, C, and D using structured binding.
auto [A, B, C, D] = taskflow.emplace([] () { std::cout \<\< "A"; },[] () { std::cout \<\< "B"; },[] () { std::cout \<\< "C"; },[] () { std::cout \<\< "D"; });
removes a task from a taskflow
| Parameters |
|---|
| task |
Removes a task and its input and output dependencies from the graph associated with the flow builder. If the task does not belong to the graph, nothing will happen.
tf::Task A = taskflow.emplace([](){ std::cout \<\< "A"; });tf::Task B = taskflow.emplace([](){ std::cout \<\< "B"; });tf::Task C = taskflow.emplace([](){ std::cout \<\< "C"; });tf::Task D = taskflow.emplace([](){ std::cout \<\< "D"; });A.precede(B, C, D);// erase A from the taskflow and its dependencies to B, C, and Dtaskflow.erase(A);
creates a module task for the target object
| Template parameters |
|---|
| T |
| Parameters |
| --- |
| object |
| Returns |
The example below demonstrates a taskflow composition using the composed_of method.
tf::Taskflow t1, t2;t1.emplace([](){ std::cout \<\< "t1"; });// t2 is partially composed of t1tf::Task comp = t2.composed\_of(t1);tf::Task init = t2.emplace([](){ std::cout \<\< "t2"; });init.precede(comp);
The taskflow object t2 is composed of another taskflow object t1, preceded by another static task init. When taskflow t2 is submitted to an executor, init will run first and then comp which spawns its definition in taskflow t1.
The target object being composed must define the method T::graph() that returns a reference to a graph object of type tf::Graph such that it can interact with the executor. For example:
// custom structstruct MyObj {tf::Graph graph;MyObj() {tf::FlowBuilder builder(graph);tf::Task task = builder.emplace([](){std::cout \<\< "a task\n";// static task});}Graph& graph() { return graph; }};MyObj obj;tf::Task comp = taskflow.composed\_of(obj);
creates a placeholder task
| Returns | a tf::Task handle |
A placeholder task maps to a node in the taskflow graph, but it does not have any callable work assigned yet. A placeholder task is different from an empty task handle that does not point to any node in a graph.
// create a placeholder task with no callable target assignedtf::Task placeholder = taskflow.placeholder();assert(placeholder.empty() == false && placeholder.has\_work() == false);// create an empty task handletf::Task task;assert(task.empty() == true);// assign the task handle to the placeholder tasktask = placeholder;assert(task.empty() == false && task.has\_work() == false);
adds adjacent dependency links to a linear list of tasks
| Parameters |
|---|
| tasks |
This member function creates linear dependencies over a vector of tasks.
tf::Task A = taskflow.emplace([](){ std::cout \<\< "A"; });tf::Task B = taskflow.emplace([](){ std::cout \<\< "B"; });tf::Task C = taskflow.emplace([](){ std::cout \<\< "C"; });tf::Task D = taskflow.emplace([](){ std::cout \<\< "D"; });std::vector\<tf::Task\> tasks {A, B, C, D}taskflow.linearize(tasks);// A-\>B-\>C-\>D
adds adjacent dependency links to a linear list of tasks
| Parameters |
|---|
| tasks |
This member function creates linear dependencies over a list of tasks.
tf::Task A = taskflow.emplace([](){ std::cout \<\< "A"; });tf::Task B = taskflow.emplace([](){ std::cout \<\< "B"; });tf::Task C = taskflow.emplace([](){ std::cout \<\< "C"; });tf::Task D = taskflow.emplace([](){ std::cout \<\< "D"; });taskflow.linearize({A, B, C, D});// A-\>B-\>C-\>D
constructs an STL-styled parallel-for task
| Template parameters |
|---|
| B |
| E |
| C |
| P |
| Parameters |
| --- |
| first |
| last |
| callable |
| part |
| Returns |
The task spawns asynchronous tasks that applies the callable object to each object obtained by dereferencing every iterator in the range [first, last). This method is equivalent to the parallel execution of the following loop:
for(auto itr=first; itr!=last; itr++) {callable(\*itr);}
Iterators can be made stateful by using std::reference_wrapper The callable needs to take a single argument of the dereferenced iterator type.
constructs an index-based parallel-for task
| Template parameters |
|---|
| B |
| E |
| S |
| C |
| P |
| Parameters |
| --- |
| first |
| last |
| step |
| callable |
| part |
| Returns |
The task spawns asynchronous tasks that applies the callable object to each index in the range [first, last) with the step size. This method is equivalent to the parallel execution of the following loop:
// case 1: step size is positivefor(auto i=first; i\<last; i+=step) {callable(i);}// case 2: step size is negativefor(auto i=first, i\>last; i+=step) {callable(i);}
Iterators can be made stateful by using std::reference_wrapper The callable needs to take a single argument of the integral index type.
constructs an index range-based parallel-for task
| Template parameters |
|---|
| R |
| C |
| P |
| Parameters |
| --- |
| range |
| callable |
| part |
| Returns |
The task spawns asynchronous tasks that applies the callable object to in the range [first, last) with the step size.
// [0, 17) with a step size of 2 using tf::IndexRangetf::IndexRange\<int\> range(0, 17, 2);// parallelize the sequence [0, 2, 4, 6, 8, 10, 12, 14, 16]taskflow.for\_each\_by\_index(range, [](tf::IndexRange\<int\> range) {// iterate each index in the subrangefor(int i=range.begin(); i\<range.end(); i+=range.step\_size()) {printf("iterate %d\n", i);}});executor.run(taskflow).wait();
The callable needs to take a single argument of type tf::IndexRange.
constructs a parallel-transform task
| Template parameters |
|---|
| B |
| E |
| O |
| C |
| P |
| Parameters |
| --- |
| first1 |
| last1 |
| d_first |
| c |
| part |
| Returns |
The task spawns asynchronous tasks that applies the callable object to an input range and stores the result in another output range. This method is equivalent to the parallel execution of the following loop:
while (first1 != last1) {\*d\_first++ = c(\*first1++);}
Iterators can be made stateful by using std::reference_wrapper The callable needs to take a single argument of the dereferenced iterator type.
constructs a parallel-transform task
| Template parameters |
|---|
| B1 |
| E1 |
| B2 |
| O |
| C |
| P |
| Parameters |
| --- |
| first1 |
| last1 |
| first2 |
| d_first |
| c |
| part |
| Returns |
The task spawns asynchronous tasks that applies the callable object to two input ranges and stores the result in another output range. This method is equivalent to the parallel execution of the following loop:
while (first1 != last1) {\*d\_first++ = c(\*first1++, \*first2++);}
Iterators can be made stateful by using std::reference_wrapper The callable needs to take two arguments of dereferenced elements from the two input ranges.
constructs an STL-styled parallel-reduction task
| Template parameters |
|---|
| B |
| E |
| T |
| O |
| P |
| Parameters |
| --- |
| first |
| last |
| init |
| bop |
| part |
| Returns |
The task spawns asynchronous tasks to perform parallel reduction over init and the elements in the range [first, last). The reduced result is store in init. This method is equivalent to the parallel execution of the following loop:
for(auto itr=first; itr!=last; itr++) {init = bop(init, \*itr);}
Iterators can be made stateful by using std::reference_wrapper
constructs an index range-based parallel-reduction task
| Template parameters |
|---|
| R |
| T |
| L |
| G |
| P |
| Parameters |
| --- |
| range |
| init |
| lop |
| gop |
| part |
| Returns |
The task spawns asynchronous tasks to perform parallel reduction over a range with init. The reduced result is store in init. Unlike the iterator-based reduction, index range-based reduction is particularly useful for applications that benefit from SIMD optimizations or other range-based processing strategies.
const size\_t N = 1000000;std::vector\<int\> data(N);// uninitialized data vectorint res = 1;// res will participate in the reductiontaskflow.reduce\_by\_index(tf::IndexRange\<size\_t\>(0, N, 1),// final resultres,// local reducer[&](tf::IndexRange\<size\_t\> subrange, std::optional\<int\> running\_total) -\> int {int residual = running\_total ? \*running\_total : 0.0;for(size\_t i=subrange.begin(); i\<subrange.end(); i+=subrange.step\_size()) {data[i] = 1.0;residual += data[i];}printf("partial sum = %lf\n", residual);return residual;},// global reducerstd::plus\<int\>());executor.run(taskflow).wait();assert(res = N + 1);
Range can be made stateful by using std::reference_wrapper.
constructs an STL-styled parallel transform-reduce task
| Template parameters |
|---|
| B |
| E |
| T |
| BOP |
| UOP |
| P |
| Parameters |
| --- |
| first |
| last |
| init |
| bop |
| uop |
| part |
| Returns |
The task spawns asynchronous tasks to perform parallel reduction over init and the transformed elements in the range [first, last). The reduced result is store in init. This method is equivalent to the parallel execution of the following loop:
for(auto itr=first; itr!=last; itr++) {init = bop(init, uop(\*itr));}
Iterators can be made stateful by using std::reference_wrapper
constructs an STL-styled parallel transform-reduce task
| Template parameters |
|---|
| B1 |
| E1 |
| B2 |
| T |
| BOP_R |
| BOP_T |
| P |
| Parameters |
| --- |
| first1 |
| last1 |
| first2 |
| init |
| bop_r |
| bop_t |
| part |
| Returns |
The task spawns asynchronous tasks to perform parallel reduction over init and transformed elements in the range [first, last). The reduced result is store in init. This method is equivalent to the parallel execution of the following loop:
for(auto itr1=first1, itr2=first2; itr1!=last1; itr1++, itr2++) {init = bop\_r(init, bop\_t(\*itr1, \*itr2));}
Iterators can be made stateful by using std::reference_wrapper
creates an STL-styled parallel inclusive-scan task
| Template parameters |
|---|
| B |
| E |
| D |
| BOP |
| Parameters |
| --- |
| first |
| last |
| d_first |
| bop |
Performs the cumulative sum (aka prefix sum, aka scan) of the input range and writes the result to the output range. Each element of the output range contains the running total of all earlier elements using the given binary operator for summation.
This function generates an inclusive scan, meaning that the N-th element of the output range is the sum of the first N input elements, so the N-th input element is included.
std::vector\<int\> input = {1, 2, 3, 4, 5};taskflow.inclusive\_scan(input.begin(), input.end(), input.begin(), std::plus\<int\>{});executor.run(taskflow).wait();// input is {1, 3, 6, 10, 15}
Iterators can be made stateful by using std::reference_wrapper
creates an STL-styled parallel inclusive-scan task with an initial value
| Template parameters |
|---|
| B |
| E |
| D |
| BOP |
| T |
| Parameters |
| --- |
| first |
| last |
| d_first |
| bop |
| init |
Performs the cumulative sum (aka prefix sum, aka scan) of the input range and writes the result to the output range. Each element of the output range contains the running total of all earlier elements (and the initial value) using the given binary operator for summation.
This function generates an inclusive scan, meaning the N-th element of the output range is the sum of the first N input elements, so the N-th input element is included.
std::vector\<int\> input = {1, 2, 3, 4, 5};taskflow.inclusive\_scan(input.begin(), input.end(), input.begin(), std::plus\<int\>{}, -1);executor.run(taskflow).wait();// input is {0, 2, 5, 9, 14}
Iterators can be made stateful by using std::reference_wrapper
creates an STL-styled parallel exclusive-scan task
| Template parameters |
|---|
| B |
| E |
| D |
| T |
| BOP |
| Parameters |
| --- |
| first |
| last |
| d_first |
| init |
| bop |
Performs the cumulative sum (aka prefix sum, aka scan) of the input range and writes the result to the output range. Each element of the output range contains the running total of all earlier elements (and the initial value) using the given binary operator for summation.
This function generates an exclusive scan, meaning the N-th element of the output range is the sum of the first N-1 input elements, so the N-th input element is not included.
std::vector\<int\> input = {1, 2, 3, 4, 5};taskflow.exclusive\_scan(input.begin(), input.end(), input.begin(), -1, std::plus\<int\>{});executor.run(taskflow).wait();// input is {-1, 0, 2, 5, 9}
Iterators can be made stateful by using std::reference_wrapper
creates an STL-styled parallel transform-inclusive scan task
| Template parameters |
|---|
| B |
| E |
| D |
| BOP |
| UOP |
| Parameters |
| --- |
| first |
| last |
| d_first |
| bop |
| uop |
Write the cumulative sum (aka prefix sum, aka scan) of the input range to the output range. Each element of the output range contains the running total of all earlier elements using uop to transform the input elements and using bop for summation.
This function generates an inclusive scan, meaning the Nth element of the output range is the sum of the first N input elements, so the Nth input element is included.
std::vector\<int\> input = {1, 2, 3, 4, 5};taskflow.transform\_inclusive\_scan(input.begin(), input.end(), input.begin(), std::plus\<int\>{}, [] (int item) { return -item; });executor.run(taskflow).wait();// input is {-1, -3, -6, -10, -15}
Iterators can be made stateful by using std::reference_wrapper
creates an STL-styled parallel transform-inclusive scan task
| Template parameters |
|---|
| B |
| E |
| D |
| BOP |
| UOP |
| T |
| Parameters |
| --- |
| first |
| last |
| d_first |
| bop |
| uop |
| init |
Write the cumulative sum (aka prefix sum, aka scan) of the input range to the output range. Each element of the output range contains the running total of all earlier elements (including an initial value) using uop to transform the input elements and using bop for summation.
This function generates an inclusive scan, meaning the Nth element of the output range is the sum of the first N input elements, so the Nth input element is included.
std::vector\<int\> input = {1, 2, 3, 4, 5};taskflow.transform\_inclusive\_scan(input.begin(), input.end(), input.begin(), std::plus\<int\>{}, [] (int item) { return -item; },-1);executor.run(taskflow).wait();// input is {-2, -4, -7, -11, -16}
Iterators can be made stateful by using std::reference_wrapper
creates an STL-styled parallel transform-exclusive scan task
| Template parameters |
|---|
| B |
| E |
| D |
| T |
| BOP |
| UOP |
| Parameters |
| --- |
| first |
| last |
| d_first |
| init |
| bop |
| uop |
Write the cumulative sum (aka prefix sum, aka scan) of the input range to the output range. Each element of the output range contains the running total of all earlier elements (including an initial value) using uop to transform the input elements and using bop for summation.
This function generates an exclusive scan, meaning the Nth element of the output range is the sum of the first N-1 input elements, so the Nth input element is not included.
std::vector\<int\> input = {1, 2, 3, 4, 5};taskflow.transform\_exclusive\_scan(input.begin(), input.end(), input.begin(), -1, std::plus\<int\>{},[](int item) { return -item; });executor.run(taskflow).wait();// input is {-1, -2, -4, -7, -11}
Iterators can be made stateful by using std::reference_wrapper
constructs a task to perform STL-styled find-if algorithm
| Template parameters |
|---|
| B |
| E |
| T |
| UOP |
| P |
| Parameters |
| --- |
| first |
| last |
| result |
| predicate |
| part |
Returns an iterator to the first element in the range [first, last) that satisfies the given criteria (or last if there is no such iterator). This method is equivalent to the parallel execution of the following loop:
auto find\_if(InputIt first, InputIt last, UnaryPredicate p) {for (; first != last; ++first) {if (predicate(\*first)){return first;}}return last;}
For example, the code below find the element that satisfies the given criteria (value plus one is equal to 23) from an input range of 10 elements:
std::vector\<int\> input = {1, 6, 9, 10, 22, 5, 7, 8, 9, 11};std::vector\<int\>::iterator result;taskflow.find\_if(input.begin(), input.end(), [](int i){ return i+1 = 23; }, result);executor.run(taskflow).wait();assert(\*result == 22);
Iterators can be made stateful by using std::reference_wrapper
constructs a task to perform STL-styled find-if-not algorithm
| Template parameters |
|---|
| B |
| E |
| T |
| UOP |
| P |
| Parameters |
| --- |
| first |
| last |
| result |
| predicate |
| part |
Returns an iterator to the first element in the range [first, last) that satisfies the given criteria (or last if there is no such iterator). This method is equivalent to the parallel execution of the following loop:
auto find\_if(InputIt first, InputIt last, UnaryPredicate p) {for (; first != last; ++first) {if (!predicate(\*first)){return first;}}return last;}
For example, the code below find the element that satisfies the given criteria (value is not equal to 1) from an input range of 10 elements:
std::vector\<int\> input = {1, 1, 1, 1, 22, 1, 1, 1, 1, 1};std::vector\<int\>::iterator result;taskflow.find\_if\_not(input.begin(), input.end(), [](int i){ return i == 1; }, result);executor.run(taskflow).wait();assert(\*result == 22);
Iterators can be made stateful by using std::reference_wrapper
constructs a task to perform STL-styled min-element algorithm
| Template parameters |
|---|
| B |
| E |
| T |
| C |
| P |
| Parameters |
| --- |
| first |
| last |
| result |
| comp |
| part |
Finds the smallest element in the [first, last) using the given comparison function object. The iterator to that smallest element is stored in result. This method is equivalent to the parallel execution of the following loop:
if (first == last) {return last;}auto smallest = first;++first;for (; first != last; ++first) {if (comp(\*first, \*smallest)) {smallest = first;}}return smallest;
For example, the code below find the smallest element from an input range of 10 elements.
std::vector\<int\> input = {1, 1, 1, 1, 1, -1, 1, 1, 1, 1};std::vector\<int\>::iterator result;taskflow.min\_element(input.begin(), input.end(), std::less\<int\>(), result);executor.run(taskflow).wait();assert(\*result == -1);
Iterators can be made stateful by using std::reference_wrapper
constructs a task to perform STL-styled max-element algorithm
| Template parameters |
|---|
| B |
| E |
| T |
| C |
| P |
| Parameters |
| --- |
| first |
| last |
| result |
| comp |
| part |
Finds the largest element in the [first, last) using the given comparison function object. The iterator to that largest element is stored in result. This method is equivalent to the parallel execution of the following loop:
if (first == last){return last;}auto largest = first;++first;for (; first != last; ++first) {if (comp(\*largest, \*first)) {largest = first;}}return largest;
For example, the code below find the largest element from an input range of 10 elements.
std::vector\<int\> input = {1, 1, 1, 1, 1, 2, 1, 1, 1, 1};std::vector\<int\>::iterator result;taskflow.max\_element(input.begin(), input.end(), std::less\<int\>(), result);executor.run(taskflow).wait();assert(\*result == 2);
Iterators can be made stateful by using std::reference_wrapper
constructs a dynamic task to perform STL-styled parallel sort
| Template parameters |
|---|
| B |
| E |
| C |
| Parameters |
| --- |
| first |
| last |
| cmp |
The task spawns asynchronous tasks to sort elements in the range [first, last) in parallel.
Iterators can be made stateful by using std::reference_wrapper
constructs a dynamic task to perform STL-styled parallel sort using the std::less<T> comparator, where T is the element type
| Template parameters |
|---|
| B |
| E |
| Parameters |
| --- |
| first |
| last |
The task spawns asynchronous tasks to parallel sort elements in the range [first, last) using the std::less<T> comparator, where T is the dereferenced iterator type.
Iterators can be made stateful by using std::reference_wrapper