18
18
#include < concepts>
19
19
20
20
#include " subspace/assertions/check.h"
21
- #include " subspace/fn/callable .h"
22
-
23
- // TODO: PartialOrd comes with: lt, le, ge, gt.
24
- // TODO: Eq comes with eq, ne.
25
- // TODO: Where to put these functions??
21
+ #include " subspace/fn/fn_concepts .h"
22
+ # include " subspace/fn/fn_ref.h "
23
+ # include " subspace/fn/run_fn.h "
24
+ # include " subspace/macros/lifetimebound.h "
25
+ # include " subspace/mem/forward.h "
26
26
27
27
namespace sus ::ops {
28
28
29
- using ::sus::fn::callable::CallableReturns;
30
- using ::sus::fn::callable::CallableWith;
31
-
32
29
// / Concept that combines all ordering types together.
33
30
template <class T >
34
31
concept Ordering = (std::same_as<T, std::strong_ordering> ||
@@ -88,12 +85,14 @@ concept ExclusivePartialOrd = (!WeakOrd<T, U> && PartialOrd<T, U>);
88
85
// /
89
86
// / By default this receives and returns objects by value. To receive and return
90
87
// / references, specify the type parameter, such as:
91
- // / `sus::ops::min<i32&>(a, b)`. Note that if either input is a temporary object
92
- // / this can return a reference to an object past its lifetime.
88
+ // / `sus::ops::min<i32&>(a, b)`.
89
+ // /
90
+ // / Note that if either input is a temporary object this can return a reference
91
+ // / to an object past its lifetime.
93
92
template <class T >
94
93
requires (Ord<T>)
95
- constexpr T min (T a, T b) noexcept {
96
- return a > b ? b : a ;
94
+ constexpr T min (T a sus_lifetimebound , T b sus_lifetimebound ) noexcept {
95
+ return a > b ? ::sus::forward<T>(b) : ::sus::forward<T>(a) ;
97
96
}
98
97
99
98
// / Compares and returns the minimum of two values with respect to the specified
@@ -103,11 +102,19 @@ constexpr T min(T a, T b) noexcept {
103
102
// /
104
103
// / By default this receives and returns objects by value. To receive and return
105
104
// / references, specify the type parameter, such as:
106
- // / `sus::ops::min_by<i32&>(a, b, c)`. Note that if either input is a temporary
107
- // / object this can return a reference to an object past its lifetime.
108
- template <class T , CallableReturns<std::strong_ordering, const T&, const T&> F>
109
- constexpr T min_by (T a, T b, F compare) noexcept {
110
- return compare (a, b) == std::strong_ordering::greater ? b : a;
105
+ // / `sus::ops::min_by<i32&>(a, b, c)`.
106
+ // /
107
+ // / Note that if either input is a temporary object this can return a reference
108
+ // / to an object past its lifetime.
109
+ template <class T >
110
+ constexpr T min_by (
111
+ T a sus_lifetimebound, T b sus_lifetimebound,
112
+ ::sus::fn::FnOnce<std::strong_ordering(const T&, const T&)> auto&&
113
+ compare) noexcept {
114
+ return ::sus::run_once (::sus::move (compare), a, b) ==
115
+ std::strong_ordering::greater
116
+ ? ::sus::forward<T>(b)
117
+ : ::sus::forward<T>(a);
111
118
}
112
119
113
120
// / Returns the element that gives the minimum value from the specified
@@ -117,13 +124,17 @@ constexpr T min_by(T a, T b, F compare) noexcept {
117
124
// /
118
125
// / By default this receives and returns objects by value. To receive and return
119
126
// / references, specify the type parameter, such as:
120
- // / `sus::ops::min_by_key<i32&>(a, b, k)`. Note that if either input is a
121
- // / temporary object this can return a reference to an object past its lifetime.
122
- template <class T , CallableWith<const T&> F, int &...,
123
- class K = std::invoke_result_t <F, const T&>>
124
- requires (Ord<K>)
125
- constexpr T min_by_key (T a, T b, F f) noexcept {
126
- return f (a) > f (b) ? b : a;
127
+ // / `sus::ops::min_by_key<i32&>(a, b, k)`.
128
+ // /
129
+ // / Note that if either input is a temporary object this can return a reference
130
+ // / to an object past its lifetime.
131
+ template <class T , ::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn,
132
+ int &..., class Key = std::invoke_result_t <KeyFn&, const T&>>
133
+ requires (Ord<Key>)
134
+ constexpr T min_by_key (T a sus_lifetimebound, T b sus_lifetimebound,
135
+ KeyFn f) noexcept {
136
+ return ::sus::run_mut (f, a) > ::sus::run_mut (f, b) ? ::sus::forward<T>(b)
137
+ : ::sus::forward<T>(a);
127
138
}
128
139
129
140
// / Compares and returns the maximum of two values.
@@ -132,12 +143,14 @@ constexpr T min_by_key(T a, T b, F f) noexcept {
132
143
// /
133
144
// / By default this receives and returns objects by value. To receive and return
134
145
// / references, specify the type parameter, such as:
135
- // / `sus::ops::max<i32&>(a, b)`. Note that if either input is a temporary object
136
- // / this can return a reference to an object past its lifetime.
146
+ // / `sus::ops::max<i32&>(a, b)`.
147
+ // /
148
+ // / Note that if either input is a temporary object this can return a reference
149
+ // / to an object past its lifetime.
137
150
template <class T >
138
151
requires (Ord<T>)
139
- constexpr T max (T a, T b) noexcept {
140
- return a > b ? a : b ;
152
+ constexpr T max (T a sus_lifetimebound , T b sus_lifetimebound ) noexcept {
153
+ return a > b ? ::sus::forward<T>(a) : ::sus::forward<T>(b) ;
141
154
}
142
155
143
156
// / Compares and returns the maximum of two values with respect to the specified
@@ -147,11 +160,19 @@ constexpr T max(T a, T b) noexcept {
147
160
// /
148
161
// / By default this receives and returns objects by value. To receive and return
149
162
// / references, specify the type parameter, such as:
150
- // / `sus::ops::max_by<i32&>(a, b, c)`. Note that if either input is a temporary
151
- // / object this can return a reference to an object past its lifetime.
152
- template <class T , CallableReturns<std::strong_ordering, const T&, const T&> F>
153
- constexpr T max_by (T a, T b, F compare) noexcept {
154
- return compare (a, b) == std::strong_ordering::greater ? a : b;
163
+ // / `sus::ops::max_by<i32&>(a, b, c)`.
164
+ // /
165
+ // / Note that if either input is a temporary object this can return a reference
166
+ // / to an object past its lifetime.
167
+ template <class T >
168
+ constexpr T max_by (
169
+ T a sus_lifetimebound, T b sus_lifetimebound,
170
+ ::sus::fn::FnOnce<std::strong_ordering(const T&, const T&)> auto&&
171
+ compare) noexcept {
172
+ return ::sus::run_once (::sus::move (compare), a, b) ==
173
+ std::strong_ordering::greater
174
+ ? ::sus::forward<T>(a)
175
+ : ::sus::forward<T>(b);
155
176
}
156
177
157
178
// / Returns the element that gives the maximum value from the specified
@@ -161,13 +182,17 @@ constexpr T max_by(T a, T b, F compare) noexcept {
161
182
// /
162
183
// / By default this receives and returns objects by value. To receive and return
163
184
// / references, specify the type parameter, such as:
164
- // / `sus::ops::max_by_key<i32&>(a, b, k)`. Note that if either input is a
165
- // / temporary object this can return a reference to an object past its lifetime.
166
- template <class T , CallableWith<const T&> F, int &...,
167
- class K = std::invoke_result_t <F, const T&>>
168
- requires (Ord<K>)
169
- constexpr T max_by_key (T a, T b, F f) noexcept {
170
- return f (a) > f (b) ? a : b;
185
+ // / `sus::ops::max_by_key<i32&>(a, b, k)`.
186
+ // /
187
+ // / Note that if either input is a temporary object this can return a reference
188
+ // / to an object past its lifetime.
189
+ template <class T , ::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn,
190
+ int &..., class Key = std::invoke_result_t <KeyFn&, const T&>>
191
+ requires (Ord<Key>)
192
+ constexpr T max_by_key (T a sus_lifetimebound, T b sus_lifetimebound,
193
+ KeyFn f) noexcept {
194
+ return ::sus::run_mut (f, a) > ::sus::run_mut (f, b) ? ::sus::forward<T>(a)
195
+ : ::sus::forward<T>(b);
171
196
}
172
197
173
198
// / Restrict a value to a certain interval.
@@ -177,16 +202,20 @@ constexpr T max_by_key(T a, T b, F f) noexcept {
177
202
// /
178
203
// / By default this receives and returns objects by value. To receive and return
179
204
// / references, specify the type parameter, such as:
180
- // / `sus::ops::clamp<i32&>(a, min, max)`. Note that if any input is a temporary
181
- // / object this can return a reference to an object past its lifetime.
205
+ // / `sus::ops::clamp<i32&>(a, min, max)`.
206
+ // /
207
+ // / Note that if any input is a temporary object this can return a reference to
208
+ // / an object past its lifetime.
182
209
// /
183
210
// / # Panics
184
211
// / Panics if `min > max`.
185
212
template <class T >
186
213
requires (Ord<T>)
187
- constexpr T clamp (T v, T min, T max) noexcept {
214
+ constexpr T clamp (T v sus_lifetimebound, T min sus_lifetimebound,
215
+ T max sus_lifetimebound) noexcept {
188
216
::sus::check (min <= max);
189
- return v < min ? min : (v > max ? max : v);
217
+ return v < min ? ::sus::forward<T>(min)
218
+ : (v > max ? ::sus::forward<T>(max) : ::sus::forward<T>(v));
190
219
}
191
220
192
221
} // namespace sus::ops
0 commit comments