recursion – std::array and std::vector Type Arbitrary Nested Iterable Generator Functions Implementation in C++

This is a follow-up question for the previous questions about recursive functions, including A Summation Function For Arbitrary Nested Vector Implementation In C++, A recursive_count_if Function For Various Type Arbitrary Nested Iterable Implementation in C++, A recursive_count_if Function with Specified value_type for Various Type Arbitrary Nested Iterable Implementation in C++, A recursive_count_if Function with Automatic Type Deducing from Lambda for Various Type Arbitrary Nested Iterable Implementation in C++ and A recursive_count_if Function with Unwrap Level for Various Type Arbitrary Nested Iterable Implementation in C++. In order to test these functions for arbitrary nested iterables, I am trying to implement some arbitrary nested iterable generators to construct nested std::vectors and nested std::arrays with the given parameters. The generator for std::array case is named n_dim_array_generator and another generator for std::vector is named n_dim_vector_generator. After trying to use if constexpr syntax in the previous question, I found that it is possible to use the similar technique in n_dim_array_generator function and n_dim_vector_generator function.

The usage description

For example, auto test_vector = n_dim_vector_generator<2, int>(1, 3); is expected to create a “test_vector” object which type is std::vector<std::vector<int>>. The content of this test_vector should as same as the following code.

std::vector<int> vector1;
vector1.push_back(1);
vector1.push_back(1);
vector1.push_back(1);
std::vector<std::vector<int>> test_vector;
test_vector.push_back(vector1);
test_vector.push_back(vector1);
test_vector.push_back(vector1);

There are four key part in the usage n_dim_vector_generator<2, int>(1, 3). The first number 2 represents the nested layers, the second parameter int represents the type of base elements, the third parameter 1 represents the input element which would be filled in, and the fourth parameter 3 represents the element count in each layer.

In the n_dim_array_generator function, the first parameter also represents the nested layers, but the parameter which represents the element count in each layer has been moved into the second one. Then, the third parameter represents the type of base elements and the fourth parameter represents the input element which would be filled in.

The experimental implementation

The experimental implementation of n_dim_vector_generator function and n_dim_array_generator function:

template<std::size_t dim, class T>
auto n_dim_vector_generator(T input, std::size_t times)
{
    if (dim < 0)
    {
        throw std::logic_error("Dimension can not be set less than 0");
    }
    if constexpr (dim == 0)
    {
        return input;
    }
    else
    {
        std::vector<decltype(n_dim_vector_generator<dim - 1>(input, times))> output;
        for (size_t i = 0; i < times; i++)
        {
            output.push_back(n_dim_vector_generator<dim - 1>(input, times));
        }
        return output;
    }
}

template<std::size_t dim, std::size_t times, class T>
auto n_dim_array_generator(T input)
{
    if (dim < 0)
    {
        throw std::logic_error("Dimension can not be set less than 0");
    }
    if constexpr (dim == 0)
    {
        return input;
    }
    else
    {
        std::array<decltype(n_dim_array_generator<dim - 1, times>(input)), times> output;
        for (size_t i = 0; i < times; i++)
        {
            output(i) = n_dim_array_generator<dim - 1, times>(input);
        }
        return output;
    }
}

Test cases

The test cases of n_dim_vector_generator function and n_dim_array_generator function are as below.

//  n_dim_vector_generator function usage with recursive_reduce function and recursive_count_if function
auto test_vector1 = n_dim_vector_generator<3, int>(3, 2);
std::cout << "recursive_reduce output: " << recursive_reduce(test_vector1, 0) << std::endl;
std::cout << "recursive_count_if output: " << recursive_count_if<3>(test_vector1, ()(auto& i) {return i == 3; }) << std::endl;

//  n_dim_array_generator function usage with recursive_reduce function and recursive_count_if function
auto test_array1 = n_dim_array_generator<3, 2, int>(3);
std::cout << "recursive_reduce output: " << recursive_reduce(test_array1, 0) << std::endl;
std::cout << "recursive_count_if output: " << recursive_count_if<3>(test_array1, ()(auto& i) {return i == 3; }) << std::endl;

The output of this test is as follows.

recursive_reduce output: 24
recursive_count_if output: 8
recursive_reduce output: 24
recursive_count_if output: 8

A Godbolt link is here.

All suggestions are welcome.

The summary information: