Skip to content

Commit 3260381

Browse files
committed
Replace old callable concepts with FnMut/Once in ord.h
1 parent 53ae8e5 commit 3260381

File tree

1 file changed

+73
-44
lines changed

1 file changed

+73
-44
lines changed

subspace/ops/ord.h

Lines changed: 73 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,14 @@
1818
#include <concepts>
1919

2020
#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"
2626

2727
namespace sus::ops {
2828

29-
using ::sus::fn::callable::CallableReturns;
30-
using ::sus::fn::callable::CallableWith;
31-
3229
/// Concept that combines all ordering types together.
3330
template <class T>
3431
concept Ordering = (std::same_as<T, std::strong_ordering> ||
@@ -88,12 +85,14 @@ concept ExclusivePartialOrd = (!WeakOrd<T, U> && PartialOrd<T, U>);
8885
///
8986
/// By default this receives and returns objects by value. To receive and return
9087
/// 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.
9392
template <class T>
9493
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);
9796
}
9897

9998
/// 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 {
103102
///
104103
/// By default this receives and returns objects by value. To receive and return
105104
/// 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);
111118
}
112119

113120
/// 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 {
117124
///
118125
/// By default this receives and returns objects by value. To receive and return
119126
/// 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);
127138
}
128139

129140
/// Compares and returns the maximum of two values.
@@ -132,12 +143,14 @@ constexpr T min_by_key(T a, T b, F f) noexcept {
132143
///
133144
/// By default this receives and returns objects by value. To receive and return
134145
/// 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.
137150
template <class T>
138151
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);
141154
}
142155

143156
/// 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 {
147160
///
148161
/// By default this receives and returns objects by value. To receive and return
149162
/// 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);
155176
}
156177

157178
/// 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 {
161182
///
162183
/// By default this receives and returns objects by value. To receive and return
163184
/// 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);
171196
}
172197

173198
/// Restrict a value to a certain interval.
@@ -177,16 +202,20 @@ constexpr T max_by_key(T a, T b, F f) noexcept {
177202
///
178203
/// By default this receives and returns objects by value. To receive and return
179204
/// 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.
182209
///
183210
/// # Panics
184211
/// Panics if `min > max`.
185212
template <class T>
186213
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 {
188216
::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));
190219
}
191220

192221
} // namespace sus::ops

0 commit comments

Comments
 (0)