# Deduction Guides for `blocked_nd_range`

Note

To enable this feature, define the `TBB_PREVIEW_BLOCKED_ND_RANGE_DEDUCTION_GUIDES` macro to 1.

## Description

The `blocked_nd_range` class represents a recursively divisible N-dimensional half-open interval for the oneTBB parallel algorithms. This feature extends `blocked_nd_range` to support Class Template Argument Deduction (starting from C++17). With that, you do not need to specify template arguments explicitly while creating a `blocked_nd_range` object if they can be inferred from the constructor arguments:

            oneapi::tbb::blocked_range<int> range1(0, 100);
            oneapi::tbb::blocked_range<int> range2(0, 200);
            oneapi::tbb::blocked_range<int> range3(0, 300);

            // Since 3 unidimensional ranges of type int are provided, the type of nd_range
            // can be deduced as oneapi::tbb::blocked_nd_range<int, 3>
            oneapi::tbb::blocked_nd_range nd_range(range1, range2, range3);

Note

For more detailed description of the implementation of this feature or to leave comments or feedback on the API, please refer to the [corresponding RFC](https://github.com/uxlfoundation/oneTBB/tree/master/rfcs/experimental/blocked_nd_range_ctad).

## API

### Header

    #include <oneapi/tbb/blocked_nd_range.h>

### Synopsis

    namespace oneapi {
    namespace tbb {

        template <typename Value, unsigned int N>
        class blocked_nd_range {
        public:
            // Member types and constructors defined as part of oneTBB specification
            using value_type = Value;
            using dim_range_type = blocked_range<value_type>;
            using size_type = typename dim_range_type::size_type;

            blocked_nd_range(const dim_range_type& dim0, /*exactly N arguments of type const dim_range_type&*/); // [1]
            blocked_nd_range(const value_type (&dim_size)[N], size_type grainsize = 1);                          // [2]
            blocked_nd_range(blocked_nd_range& r, split);                                                        // [3]
            blocked_nd_range(blocked_nd_range& r, proportional_split);                                           // [4]
        }; // class blocked_nd_range

        // Explicit deduction guides
        template <typename Value, typename... Values>
        blocked_nd_range(blocked_range<Value>, blocked_range<Values>...)
        -> blocked_nd_range<Value, 1 + sizeof...(Values)>;

        template <typename Value, unsigned int... Ns>
        blocked_nd_range(const Value (&...)[Ns])
        -> blocked_nd_range<Value, sizeof...(Ns)>;

        template <typename Value, unsigned int N>
        blocked_nd_range(const Value (&)[N], typename blocked_nd_range<Value, N>::size_type = 1)
        -> blocked_nd_range<Value, N>;

        template <typename Value, unsigned int N>
        blocked_nd_range(blocked_nd_range<Value, N>, split)
        -> blocked_nd_range<Value, N>;

        template <typename Value, unsigned int N>
        blocked_nd_range(blocked_nd_range<Value, N>, proportional_split)
        -> blocked_nd_range<Value, N>;
    } // namespace tbb
    } // namespace oneapi

### Deduction Guides

The copy and move constructors of `blocked_nd_range` provide implicitly generated deduction guides. In addition, the following explicit deduction guides are provided:

    template <typename Value, typename... Values>
    blocked_nd_range(blocked_range<Value>, blocked_range<Values>...)
    -> blocked_nd_range<Value, 1 + sizeof...(Values)>;

Effects: Enables deduction when a set of `blocked_range` objects is passed to the `blocked_nd_range` constructor `[1]`.

Constraints: Participates in overload resolution only if all of the types in Values are same as Value.

    template <typename Value, unsigned int... Ns>
    blocked_nd_range(const Value (&...)[Ns])
    -> blocked_nd_range<Value, sizeof...(Ns)>;

Effects: Enables deduction when a set of `blocked_range` objects is provided as braced-init-lists to the `blocked_nd_range` constructor `[1]`.

Constraints: Participates in overload resolution only if `sizeof...(Ns) >= 2`, and each integer `Ni` in `Ns` is either `2` or `3`, corresponding to `blocked_range` constructors with 2 and 3 arguments, respectively.

Note

The guide allows a deduction only from braced-init-lists containing objects of the same type. For ranges with non-integral `value_type`, setting an explicit grainsize argument is not supported by the deduction guides and requires specifying explicit template arguments.

    template <typename Value, unsigned int N>
    blocked_nd_range(const Value (&)[N], typename blocked_nd_range<Value, N>::size_type = 1)
    -> blocked_nd_range<Value, N>;

Effects: Allows deduction from a single C array object indicating a set of dimension sizes to constructor `2` of `blocked_nd_range`.

    template <typename Value, unsigned int N>
    blocked_nd_range(blocked_nd_range<Value, N>, split)
    -> blocked_nd_range<Value, N>;

Effects: Allows deduction while using the splitting constructor `3` of `blocked_nd_range`.

    template <typename Value, unsigned int N>
    blocked_nd_range(blocked_nd_range<Value, N>, proportional_split)
    -> blocked_nd_range<Value, N>;

Effects: Allows deduction while using the proportional splitting constructor `4` of `blocked_nd_range`.

### Example

        {
            oneapi::tbb::blocked_range<int> range1(0, 100);
            oneapi::tbb::blocked_range<int> range2(0, 200);

            // Deduced as blocked_nd_range<int, 2>
            oneapi::tbb::blocked_nd_range nd_range(range1, range2);
        }
        {
            // Deduced as blocked_nd_range<int, 2>
            oneapi::tbb::blocked_nd_range nd_range({0, 100}, {0, 200, 5});
        }
        {
            int endings[3] = {100, 200, 300};

            // Deduced as blocked_nd_range<int, 3>
            oneapi::tbb::blocked_nd_range nd_range1(endings);

            // Deduced as blocked_nd_range<int, 3>
            oneapi::tbb::blocked_nd_range nd_range2({100, 200, 300}, /*grainsize = */10);
        }