Horizon
minmax.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2014-present
5 // Copyright Casey Carter 2015
6 //
7 // Use, modification and distribution is subject to the
8 // Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 //
12 // Project home: https://github.com/ericniebler/range-v3
13 //
14 #ifndef RANGES_V3_ALGORITHM_MINMAX_HPP
15 #define RANGES_V3_ALGORITHM_MINMAX_HPP
16 
17 #include <initializer_list>
18 
19 #include <range/v3/range_fwd.hpp>
20 
21 #include <range/v3/algorithm/result_types.hpp>
30 #include <range/v3/utility/static_const.hpp>
31 
32 #include <range/v3/detail/prologue.hpp>
33 
34 namespace ranges
35 {
38  template<typename T>
39  using minmax_result = detail::min_max_result<T, T>;
40 
41  RANGES_FUNC_BEGIN(minmax)
42 
43 
44  template(typename T, typename C = less, typename P = identity)(
45  requires indirect_strict_weak_order<C, projected<T const *, P>>)
46  constexpr minmax_result<T const &> RANGES_FUNC(minmax)(
47  T const & a, T const & b, C pred = C{}, P proj = P{}) //
48  {
49  using R = minmax_result<T const &>;
50  return invoke(pred, invoke(proj, b), invoke(proj, a)) ? R{b, a} : R{a, b};
51  }
52 
54  template(typename Rng, typename C = less, typename P = identity)(
55  requires input_range<Rng> AND
56  indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> AND
57  indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>)
58  constexpr minmax_result<range_value_t<Rng>> //
59  RANGES_FUNC(minmax)(Rng && rng, C pred = C{}, P proj = P{}) //
60  {
61  using R = minmax_result<range_value_t<Rng>>;
62  auto first = ranges::begin(rng);
63  auto last = ranges::end(rng);
64  RANGES_EXPECT(first != last);
65  auto result = R{*first, *first};
66  if(++first != last)
67  {
68  {
69  auto && tmp = *first;
70  if(invoke(pred, invoke(proj, tmp), invoke(proj, result.min)))
71  result.min = (decltype(tmp) &&)tmp;
72  else
73  result.max = (decltype(tmp) &&)tmp;
74  }
75  while(++first != last)
76  {
77  range_value_t<Rng> tmp1 = *first;
78  if(++first == last)
79  {
80  if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min)))
81  result.min = std::move(tmp1);
82  else if(!invoke(
83  pred, invoke(proj, tmp1), invoke(proj, result.max)))
84  result.max = std::move(tmp1);
85  break;
86  }
87 
88  auto && tmp2 = *first;
89  if(invoke(pred, invoke(proj, tmp2), invoke(proj, tmp1)))
90  {
91  if(invoke(pred, invoke(proj, tmp2), invoke(proj, result.min)))
92  result.min = (decltype(tmp2) &&)tmp2;
93  if(!invoke(pred, invoke(proj, tmp1), invoke(proj, result.max)))
94  result.max = std::move(tmp1);
95  }
96  else
97  {
98  if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min)))
99  result.min = std::move(tmp1);
100  if(!invoke(pred, invoke(proj, tmp2), invoke(proj, result.max)))
101  result.max = (decltype(tmp2) &&)tmp2;
102  }
103  }
104  }
105  return result;
106  }
107 
109  template(typename T, typename C = less, typename P = identity)(
110  requires copyable<T> AND
111  indirect_strict_weak_order<C, projected<T const *, P>>)
112  constexpr minmax_result<T> RANGES_FUNC(minmax)(
113  std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) //
114  {
115  return (*this)(rng, std::move(pred), std::move(proj));
116  }
117 
118  RANGES_FUNC_END(minmax)
119 
120  namespace cpp20
121  {
122  using ranges::minmax;
123  using ranges::minmax_result;
124  } // namespace cpp20
126 } // namespace ranges
127 
128 #include <range/v3/detail/epilogue.hpp>
129 
130 #endif
CPP_concept indirect_strict_weak_order
\concept indirect_strict_weak_order
Definition: concepts.hpp:689
CPP_concept indirectly_copyable_storable
\concept indirectly_copyable_storable
Definition: concepts.hpp:798
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
bool_<(T::type::value< U::type::value)> less
A Boolean integral constant wrapper around true if T::type::value is less than U::type::value; false,...
Definition: meta.hpp:255