This is a follow-up question for A Maximum Function For Various Type Arbitrary Nested Iterable Implementation in C++. Besides the function for finding maximum, I am trying to implement recursive_minmax
template function which returns both minimum and maximum values.
The experimental implementation
recursive_minmax
template function implementationtemplate<class T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = std::ranges::less> requires(!(std::ranges::input_range<T>)) // non-range overloading constexpr auto recursive_minmax(const T& input, Comp comp = {}, Proj proj = {}) { return input; } template<std::ranges::input_range T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = std::ranges::less> constexpr auto recursive_minmax(const T& numbers, Comp comp = {}, Proj proj = {}) { return std::make_pair( recursive_min(numbers, comp, proj), recursive_max(numbers, comp, proj) ); }
recursive_min
template function implementationtemplate<class T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = std::ranges::less> requires(!std::ranges::input_range<T>) // non-range overloading static inline T recursive_min(T inputNumber, Comp comp = {}, Proj proj = {}) { return std::invoke(proj, inputNumber); } template<std::ranges::input_range T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = std::ranges::less> static inline auto recursive_min(const T& numbers, Comp comp = {}, Proj proj = {}) { auto output = recursive_min(numbers.at(0), comp, proj); for (auto& element : numbers) { output = std::ranges::min( output, recursive_min(element, comp, proj), comp, proj); } return output; }
recursive_max
template function implementationtemplate<class T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = std::ranges::less> requires(!std::ranges::input_range<T>) // non-range overloading static inline T recursive_max(T inputNumber, Comp comp = {}, Proj proj = {}) { return std::invoke(proj, inputNumber); } template<std::ranges::input_range T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = std::ranges::less> static inline auto recursive_max(const T& numbers, Comp comp = {}, Proj proj = {}) { auto output = recursive_max(numbers.at(0), comp, proj); for (auto& element : numbers) { output = std::ranges::max( output, recursive_max(element, comp, proj), comp, proj); } return output; }
Full Testing Code
The full testing code:
// A `recursive_minmax` Template Function Implementation in C++
#include <algorithm>
#include <array>
#include <chrono>
#include <concepts>
#include <execution>
#include <iostream>
#include <ranges>
#include <vector>
template<class T>
requires (std::ranges::input_range<T>)
constexpr auto recursive_print(const T& input, const int level = 0)
{
T output = input;
std::cout << std::string(level, ' ') << "Level " << level << ":" << "\n";
std::transform(input.cbegin(), input.cend(), output.begin(),
[level](auto&& x)
{
std::cout << std::string(level, ' ') << x << "\n";
return x;
}
);
return output;
}
template<class T>
requires (std::ranges::input_range<T> &&
std::ranges::input_range<std::ranges::range_value_t<T>>)
constexpr T recursive_print(const T& input, const int level = 0)
{
T output = input;
std::cout << std::string(level, ' ') << "Level " << level << ":" << "\n";
std::transform(input.cbegin(), input.cend(), output.begin(),
[level](auto&& element)
{
return recursive_print(element, level + 1);
}
);
return output;
}
bool comp(int a, int b){
return a > b;
}
template<class T, class Proj = std::identity,
std::indirect_strict_weak_order<
std::projected<const T*, Proj>> Comp = std::ranges::less>
requires(!std::ranges::input_range<T>) // non-range overloading
static inline T recursive_min(T inputNumber, Comp comp = {}, Proj proj = {})
{
return std::invoke(proj, inputNumber);
}
template<std::ranges::input_range T, class Proj = std::identity,
std::indirect_strict_weak_order<
std::projected<const T*, Proj>> Comp = std::ranges::less>
static inline auto recursive_min(const T& numbers, Comp comp = {}, Proj proj = {})
{
auto output = recursive_min(numbers.at(0), comp, proj);
for (auto& element : numbers)
{
output = std::ranges::min(
output,
recursive_min(std::invoke(proj, element), comp, proj),
comp,
proj);
}
return output;
}
template<class T, class Proj = std::identity,
std::indirect_strict_weak_order<
std::projected<const T*, Proj>> Comp = std::ranges::less>
requires(!std::ranges::input_range<T>) // non-range overloading
static inline T recursive_max(T inputNumber, Comp comp = {}, Proj proj = {})
{
return std::invoke(proj, inputNumber);
}
template<std::ranges::input_range T, class Proj = std::identity,
std::indirect_strict_weak_order<
std::projected<const T*, Proj>> Comp = std::ranges::less>
static inline auto recursive_max(const T& numbers, Comp comp = {}, Proj proj = {})
{
auto output = recursive_max(numbers.at(0), comp, proj);
for (auto& element : numbers)
{
output = std::ranges::max(
output,
recursive_max(std::invoke(proj, element), comp, proj),
comp,
proj);
}
return output;
}
template<class T, class Proj = std::identity,
std::indirect_strict_weak_order<
std::projected<const T*, Proj>> Comp = std::ranges::less>
requires(!(std::ranges::input_range<T>)) // non-range overloading
constexpr auto recursive_minmax(const T& input, Comp comp = {}, Proj proj = {})
{
return std::invoke(proj, input);
}
template<std::ranges::input_range T, class Proj = std::identity,
std::indirect_strict_weak_order<
std::projected<const T*, Proj>> Comp = std::ranges::less>
constexpr auto recursive_minmax(const T& numbers, Comp comp = {}, Proj proj = {})
{
return std::make_pair(
recursive_min(numbers, comp, proj),
recursive_max(numbers, comp, proj)
);
}
void recursive_minmax_test()
{
std::array test_array1{3, 1, 4, 1, 5, 15, 2, 6, 5};
std::array test_array2{3, 1, 4, -1, 5, 9, 2, 6, 5};
std::vector<decltype(test_array1)> v = {test_array1, test_array2};
auto [min, max] = recursive_minmax(v);
std::cout << "Min value is " << min << "\n";
std::cout << "Max value is " << max << "\n";
}
int main()
{
auto start = std::chrono::system_clock::now();
recursive_minmax_test();
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
std::cout << "Computation finished at " << std::ctime(&end_time) << "elapsed time: " << elapsed_seconds.count() << '\n';
return 0;
}
The output of the test code above:
Min value is -1
Max value is 15
Computation finished at Sun Dec 3 08:04:27 2023
elapsed time: 3.4378e-05
All suggestions are welcome.
The summary information:
Which question it is a follow-up to?
A Maximum Function For Various Type Arbitrary Nested Iterable Implementation in C++
What changes has been made in the code since last question?
I am trying to implement
recursive_minmax
template function in this post.Why a new review is being asked for?
Please review
recursive_minmax
template function implementation and all suggestions are welcome.