This is a follow-up question for A recursive_count_if Function For Various Type Arbitrary Nested Iterable Implementation in C++ and A recursive_count_if Function with Specified value_type for Various Type Arbitrary Nested Iterable Implementation in C++. After digging into the thing that detecting the argument type of a function, I found that it is possible to simplify the T1
parameter in last implementation with boost::callable_traits::args_t
syntax in Boost.CallableTraits
library. As the result, recursive_count_if
template function can be used exactly as the following code.
std::vector<std::vector<std::string>> v = {{"hello"}, {"world"}};
auto size5 = [](std::string s) { return s.size() == 5; };
auto n = recursive_count_if(v, size5);
The implementation of recursive_count_if
function with automatic type deducing:
#include <boost/callable_traits.hpp>
// recursive_count_if implementation
template<class T1, class T2> requires (is_iterable<T1> && std::same_as<std::tuple<std::iter_value_t<T1>>, boost::callable_traits::args_t<T2>>)
auto recursive_count_if(const T1& input, const T2 predicate)
{
return std::count_if(input.begin(), input.end(), predicate);
}
// transform_reduce version
template<class T1, class T2> requires (is_iterable<T1> && !std::same_as<std::tuple<std::iter_value_t<T1>>, boost::callable_traits::args_t<T2>>)
auto recursive_count_if(const T1& input, const T2 predicate)
{
return std::transform_reduce(std::begin(input), std::end(input), std::size_t{}, std::plus<std::size_t>(), [predicate](auto& element) {
return recursive_count_if(element, predicate);
});
}
The used is_iterable
concept:
template<typename T>
concept is_iterable = requires(T x)
{
*std::begin(x);
std::end(x);
};
The constraints of usage
Because the type in the input lambda function plays the role of termination condition, you can not use auto
keyword as generic lambdas here. If the lambda function like [](auto element) { }
is passed in, compiling errors will pop up. If you want to use generic lambdas, maybe you can choose the previous version recursive_count_if
function due to the termination condition is separated.
All suggestions are welcome.
The summary information:
Which question it is a follow-up to?
A recursive_count_if Function For Various Type Arbitrary Nested Iterable Implementation in C++ and
What changes has been made in the code since last question?
This version of
recursive_count_if
template function is boost-dependent, and the type of termination condition can be deduced automatically from input lambda parameter.Why a new review is being asked for?
In my opinion, the requires-clause of
recursive_count_if
template function is a little complex and it's boost-dependent. If there is any simpler way to do this, please let me know.
recursive
? \$\endgroup\$std::vector<std::vector<std::vector<std::string>>>
orstd::vector<std::vector<std::vector<std::vector<std::string>>>>
... \$\endgroup\$