# A recursive_count Function For Various Type Arbitrary Nested Iterable Implementation in C++

Posted on

Problem

This is a follow-up question for A Summation Function For Arbitrary Nested Vector Implementation In C++ and A Summation Function For Various Type Arbitrary Nested Iterable Implementation in C++. Besides the summation result, I am trying to get the element count in arbitrary nested iterable things. For example, there are three elements in `std::vector<int> test_vector = { 1, 2, 3 };`, so the element count of `test_vector` is `3`. The experimental implementation of `recursive_count` is as below.

``````size_t recursive_count()
{
return 0;
}

template<class T> requires (!is_elements_iterable<T> && !is_iterable<T>)
size_t recursive_count(const T& input)
{
return 1;
}

template<class T> requires (!is_elements_iterable<T> && is_iterable<T>)
size_t recursive_count(const T& input)
{
return input.size();
}

template<class T> requires (is_elements_iterable<T> && is_iterable<T>)
size_t recursive_count(const T& input)
{
size_t output{};
for (auto &element : input)
{
output += recursive_count(element);
}
return output;
}
``````

Some test cases of this `recursive_count` template function.

``````//  std::vector<int> case
std::vector<int> test_vector = {
1, 2, 3
};
auto recursive_count_result1 = recursive_count(test_vector);
std::cout << recursive_count_result1 << std::endl;

//  std::vector<std::vector<int>> case
std::vector<decltype(test_vector)> test_vector2 = {
test_vector, test_vector, test_vector
};
auto recursive_count_result2 = recursive_count(test_vector2);
std::cout << recursive_count_result2 << std::endl;

// std::deque<int> case
std::deque<int> test_deque;
test_deque.push_back(1);
test_deque.push_back(1);
test_deque.push_back(1);
auto recursive_count_result3 = recursive_count(test_deque);
std::cout << recursive_count_result3 << std::endl;

// std::deque<std::deque<int>> case
std::deque<decltype(test_deque)> test_deque2;
test_deque2.push_back(test_deque);
test_deque2.push_back(test_deque);
test_deque2.push_back(test_deque);
auto recursive_count_result4 = recursive_count(test_deque2);
std::cout << recursive_count_result4 << std::endl;
``````

All suggestions are welcome.

The summary information:

• Which question it is a follow-up to?

A Summation Function For Various Type Arbitrary Nested Iterable Implementation in C++

• What changes has been made in the code since last question?

The previous questions are focused on summation operation, and I am trying to implement a `recursive_count` template function here.

• Why a new review is being asked for?

In my opinion, I am not sure the name of this function is good or not. I know there is a function `std::count` in STL which purpose is to count the elements that are equal to given specific value. If there is any better naming suggestion, please let me know.

Solution

# No need for an overload that takes no parameters

Nothing calls `recursive_count()` without parameters, so that overload is unnecessary.

# Unnecessary requirements

You don’t need to require both `is_elements_iterable<T>` and `is_iterable<T>`, the former will already cover the requirements of the latter, and if you negate them then the latter covers the former. So the overloads should be:

``````template<class T> requires !is_iterable<T>
size_t recursive_count(const T& input)
{
return 1;
}

template<class T> requires (!is_elements_iterable<T> && is_iterable<T>)
size_t recursive_count(const T& input)
{
return input.size();
}

template<class T> requires is_elements_iterable<T>
size_t recursive_count(const T& input)
{
size_t output{};
for (auto &element : input)
{
output += recursive_count(element);
}
return output;
}
``````

# Naming

Indeed you already noticed that STL has a `std::count` that does something different. However there is a function that does what you want for non-nested containers: `std::size`. So consider naming your function `std::recursive_size`.

# Consider making more use of STL algorithms

You are implementing your own algorithms but you are not making use of STL’s algorithms. This can reduce the amount of code you write. For example, the last overload can be rewritten as:

``````template<class T> requires is_elements_iterable<T>
size_t recursive_count(const T& input)
{
return std::transform_reduce(std::begin(input), std::end(input), std::size_t{}, std::plus<std::size_t>(), [](auto &element){
return recursive_count(element);
});
}
``````