# Parallel Reduction for rvalues

## Description

oneAPI Threading Building Blocks (oneTBB) implementation extends the ParallelReduceFunc and ParallelReduceReduction to optimize operating with `rvalues` using functional form of `tbb::parallel_reduce` and `tbb::parallel_deterministic_reduce` algorithms.

## API

### Header

    #include <oneapi/tbb/parallel_reduce.h>

### ParallelReduceFunc Requirements: Pseudo-Signature, Semantics

Value Func::operator()(const Range &range, Value &&x) const

or

Value Func::operator()(const Range &range, const Value &x) const

  Accumulates the result for a subrange, starting with initial value `x`. The `Range` type must meet the Range requirements. The `Value` type must be the same as a corresponding template parameter for the parallel_reduce algorithm.

  If both `rvalue` and `lvalue` forms are provided, the `rvalue` is preferred.

### ParallelReduceReduction Requirements: Pseudo-Signature, Semantics

Value Reduction::operator()(Value &&x, Value &&y) const

or

Value Reduction::operator()(const Value &x, const Value &y) const

  Combines the `x` and `y` results. The `Value` type must be the same as a corresponding template parameter for the parallel_reduce algorithm.

  If both `rvalue` and `lvalue` forms are provided, the `rvalue` is preferred.

## Example

    // C++17
    #include <oneapi/tbb/parallel_reduce.h>
    #include <oneapi/tbb/blocked_range.h>
    #include <vector>
    #include <set>

    int main() {
        std::vector<std::set<int>> sets;

        oneapi::tbb::parallel_reduce(oneapi::tbb::blocked_range<size_t>(0, sets.size()),
                                        std::set<int>{}, // identity element - empty set
                                        [&](const oneapi::tbb::blocked_range<size_t>& range, std::set<int>&& value) {
                                            for (size_t i = range.begin(); i < range.end(); ++i) {
                                                // Having value as a non-const rvalue reference allows to efficiently
                                                // transfer nodes from sets[i] without copying/moving the data
                                                value.merge(std::move(sets[i]));
                                            }
                                            return value;
                                        },
                                        [&](std::set<int>&& x, std::set<int>&& y) {
                                            x.merge(std::move(y));
                                            return x;
                                        }
                                        );
    }

See also

- oneapi::tbb::parallel_reduce specification

- oneapi::tbb::parallel_deterministic_reduce specification

- ParallelReduceFunc specification

- ParallelReduceReduction specification