Horizon
Loading...
Searching...
No Matches
minmax.hpp
Go to the documentation of this file.
1
2// 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
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
34namespace 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
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