minmax.h 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. //
  2. // minmax.h
  3. // stream
  4. //
  5. // Created by Sam Jaffe on 3/30/23.
  6. //
  7. #pragma once
  8. #include <stream/forward.h>
  9. #include <stream/detail/identity.h>
  10. #include <stream/detail/invoke.h>
  11. #include <stream/detail/named_pair.h>
  12. #include <stream/detail/traits.h>
  13. #include <stream/detail/macro.h>
  14. namespace stream::ranges {
  15. template <typename T, typename Comp = std::less<>,
  16. typename Proj = detail::identity>
  17. auto minmax(T const & l, T const & r, Comp comp = {}, Proj proj = {})
  18. -> detail::min_max_result<T const &, T const &> {
  19. if (detail::invoke(comp, l, r, proj, proj)) { return {l, r}; }
  20. return {r, l};
  21. }
  22. template <typename It, typename S, typename Comp = std::less<>,
  23. typename Proj = detail::identity,
  24. REQUIRES((detail::is_comparable_v<It, S>))>
  25. auto minmax_element(It it, S end, Comp comp = {}, Proj proj = {}) {
  26. detail::min_max_result rval(it, it);
  27. for (++it; it != end; ++it) {
  28. if (detail::invoke(comp, it, rval.min, proj, proj)) {
  29. rval.min = it;
  30. } else if (detail::invoke(comp, rval.max, it, proj, proj)) {
  31. rval.max = it;
  32. }
  33. }
  34. return rval;
  35. }
  36. template <typename Stream, typename Comp = std::less<>,
  37. typename Proj = detail::identity>
  38. auto minmax_element(Stream const & stream, Comp comp = {}, Proj proj = {}) {
  39. return minmax_element(stream.begin(), stream.end(), std::ref(comp),
  40. std::ref(proj));
  41. }
  42. template <typename T, typename Comp = std::less<>,
  43. typename Proj = detail::identity>
  44. auto minmax(std::initializer_list<T> stream, Comp comp = {}, Proj proj = {}) {
  45. auto result = minmax_element(stream.begin(), stream.end(), std::ref(comp),
  46. std::ref(proj));
  47. return detail::min_max_result(*result.min, *result.max);
  48. }
  49. template <typename Stream, typename Comp = std::less<>,
  50. typename Proj = detail::identity>
  51. auto minmax(Stream const & stream, Comp comp = {}, Proj proj = {}) {
  52. auto result = minmax_element(stream.begin(), stream.end(), std::ref(comp),
  53. std::ref(proj));
  54. return detail::min_max_result(*result.min, *result.max);
  55. }
  56. }
  57. #include <stream/detail/undef.h>