// // minmax.h // stream // // Created by Sam Jaffe on 3/30/23. // #pragma once #include #include #include #include #include #include namespace stream::ranges { template , typename Proj = detail::identity> auto minmax(T const & l, T const & r, Comp comp = {}, Proj proj = {}) -> detail::min_max_result { if (detail::invoke(comp, l, r, proj, proj)) { return {l, r}; } return {r, l}; } template , typename Proj = detail::identity, REQUIRES((detail::is_comparable_v))> auto minmax_element(It it, S end, Comp comp = {}, Proj proj = {}) { detail::min_max_result rval(it, it); for (++it; it != end; ++it) { if (detail::invoke(comp, it, rval.min, proj, proj)) { rval.min = it; } else if (detail::invoke(comp, rval.max, it, proj, proj)) { rval.max = it; } } return rval; } template , typename Proj = detail::identity> auto minmax_element(Stream const & stream, Comp comp = {}, Proj proj = {}) { return minmax_element(stream.begin(), stream.end(), std::ref(comp), std::ref(proj)); } template , typename Proj = detail::identity> auto minmax(std::initializer_list stream, Comp comp = {}, Proj proj = {}) { auto result = minmax_element(stream.begin(), stream.end(), std::ref(comp), std::ref(proj)); return detail::min_max_result(*result.min, *result.max); } template , typename Proj = detail::identity> auto minmax(Stream const & stream, Comp comp = {}, Proj proj = {}) { auto result = minmax_element(stream.begin(), stream.end(), std::ref(comp), std::ref(proj)); return detail::min_max_result(*result.min, *result.max); } } #include