19#pragma region Const/Mut
21 template<
class Ret,
class Class,
class... Args>
22 constexpr auto Const(Ret (Class::*ptr)(Args...) const) {
return ptr; }
23 template<
class Ret,
class Class,
class... Args>
24 constexpr auto Mut(Ret (Class::*ptr)(Args...)) {
return ptr; }
26 template<
class Ret,
class Class,
class... Args>
27 constexpr auto ConstFn(Ret (Class::*ptr)(Args...) const) {
return std::mem_fn(ptr); }
28 template<
class Ret,
class Class,
class... Args>
29 constexpr auto MutFn(Ret (Class::*ptr)(Args...)) {
return std::mem_fn(ptr); }
37 template<
class Opt,
class Err>
38 constexpr std::expected<typename std::remove_cvref_t<Opt>::value_type, Err>
ValueOr(Opt&& val, Err&& err) {
40 if constexpr (std::is_rvalue_reference_v<Opt>)
41 return std::move(*val);
45 return std::unexpected{ std::forward<Err>(err) };
49 template<
class Opt,
class Err>
51 using OptT = std::optional<Opt>&&;
52 using ValT =
typename std::remove_cvref_t<OptT>::value_type;
54 return [err = std::forward<Err>(err)](OptT val) -> std::expected<ValT, Err> {
56 if constexpr (std::is_rvalue_reference_v<OptT>)
57 return std::move(*val);
61 return std::unexpected{ err };
68#pragma region CallIfError/Not
70 template<
bool Negate,
class Pred,
class Trans,
class Val>
71 requires std::predicate<Pred&, Val&> && std::invocable<Trans, Val>
72 constexpr std::expected<Val, std::invoke_result_t<Trans, Val>>
74 if (std::invoke(pred, value) ^ Negate)
75 return std::forward<Val>(value);
76 return std::unexpected{ std::invoke(trans, std::forward<Val>(value)) };
81 template<
class Pred,
class Trans,
class Val>
82 constexpr auto CallIfError(Pred&& pred, Trans&& trans, Val&& value) {
83 return S_CallIfErrorImpl<false>(
84 std::forward<Pred>(pred),
85 std::forward<Trans>(trans),
86 std::forward<Val>(value)
91 template<auto Pred,
class Trans,
class Val>
93 return CallIfError(ToValue<Pred>(), std::forward<Trans>(trans), std::forward<Val>(val));
97 template<auto Pred, auto Trans,
class Val>
99 return CallIfError(ToValue<Pred>(), ToValue<Trans>(), std::forward<Val>(val));
104 template<
class Pred,
class Trans,
class Val>
106 return S_CallIfErrorImpl<true>(
107 std::forward<Pred>(pred),
108 std::forward<Trans>(trans),
109 std::forward<Val>(value)
114 template<auto Pred,
class Trans,
class Val>
116 return CallIfErrorNot(ToValue<Pred>(), std::forward<Trans>(trans), std::forward<Val>(val));
120 template<auto Pred, auto Trans,
class Val>
122 return CallIfErrorNot(ToValue<Pred>(), ToValue<Trans>(), std::forward<Val>(val));
126 template<
class Pred,
class Trans>
128 return [pred = std::forward<Pred>(pred),
129 trans = std::forward<Trans>(trans)](
auto&& value) {
130 return CallIfError(pred, trans, std::forward<
decltype(value)>(value));
135 template<auto Pred,
class Trans>
137 return [trans = std::forward<Trans>(trans)](
auto&& value) {
138 return CallIfError(ToValue<Pred>(), trans, std::forward<
decltype(value)>(value));
143 template<auto Pred, auto Trans>
145 return CallIfErrorHof<Pred, Trans>(ToValue<Pred>(), ToValue<Trans>());
149 template<
class Pred,
class Trans>
151 return [pred = std::forward<Pred>(pred),
152 trans = std::forward<Trans>(trans)](
auto&& value) {
153 return CallIfErrorNot(pred, trans, std::forward<
decltype(value)>(value));
158 template<auto Pred,
class Trans>
160 return [trans = std::forward<Trans>(trans)](
auto&& value) {
161 return CallIfErrorNot(ToValue<Pred>(), trans, std::forward<
decltype(value)>(value));
166 template<auto Pred, auto Trans>
168 return CallIfErrorNotHof<Pred, Trans>(ToValue<Pred>(), ToValue<Trans>());
173#pragma region ErrorIf/Not
175 template<
bool Negate,
class Pred,
class Val>
176 requires std::predicate<Pred&, Val&>
178 return std::invoke(pred, value) ^ Negate;
181 template<
bool Negate,
class Pred,
class Val,
class Err>
182 requires std::predicate<Pred&, Val&>
183 constexpr std::expected<Val, std::decay_t<Err>>
185 if (!S_TestIfImpl<Negate>(pred, value))
186 return std::forward<Val>(value);
187 return std::unexpected{ std::forward<Err>(error) };
191 template<
class Pred,
class Val,
class Err>
192 constexpr auto ErrorIf(Pred&& pred, Val&& value, Err&& error) {
193 return S_ErrorIfImpl<false>(
194 std::forward<Pred>(pred),
195 std::forward<Val>(value),
196 std::forward<Err>(error)
201 template<auto Pred,
class Val,
class Err>
202 constexpr auto ErrorIf(Val&& value, Err&& error) {
203 return ErrorIf(ToValue<Pred>(), std::forward<Val>(value), std::forward<Err>(error));
207 template<
class Pred,
class Val,
class Err>
208 constexpr auto ErrorIfNot(Pred&& pred, Val&& value, Err&& error) {
209 return S_ErrorIfImpl<true>(
210 std::forward<Pred>(pred),
211 std::forward<Val>(value),
212 std::forward<Err>(error)
217 template<auto Pred,
class Val,
class Err>
219 return ErrorIf(ToValue<Pred>(), std::forward<Val>(value), std::forward<Err>(error));
223 template<
class Pred,
class Err>
225 return [pred = std::forward<Pred>(pred),
226 error = std::forward<Err>(error)](
auto&& value) {
227 return ErrorIf(pred, std::forward<
decltype(value)>(value), error);
232 template<auto Pred,
class Err>
234 return [error = std::forward<Err>(error)](
auto&& value) {
235 return ErrorIf(ToValue<Pred>(), std::forward<
decltype(value)>(value), error);
239 template<
class Pred,
class Err>
241 return [pred = std::forward<Pred>(pred),
242 error = std::forward<Err>(error)](
auto&& value) {
243 return ErrorIfNot(pred, std::forward<
decltype(value)>(value), error);
247 template<auto Pred,
class Err>
249 return [error = std::forward<Err>(error)](
auto&& value) {
250 return ErrorIfNot(ToValue<Pred>(), std::forward<
decltype(value)>(value), error);
257#pragma region Transform{Opt,Exp}If/Not
259 template<
bool Negate,
class Pred,
class Trans,
class Val>
260 requires std::predicate<Pred&, Val&> && std::invocable<Trans, Val>
262 -> std::optional<std::invoke_result_t<Trans, Val>>
264 if (std::invoke(pred, value) ^ Negate)
265 return std::invoke(trans, std::forward<Val>(value));
269 template<
bool Negate,
class Pred,
class Trans,
class Val,
class Err>
270 requires std::predicate<Pred&, Val&> && std::invocable<Trans, Val>
272 -> std::expected<std::invoke_result_t<Trans, Val>, std::decay_t<Err>>
274 if (std::invoke(pred, value) ^ Negate)
275 return std::invoke(trans, std::forward<Val>(value));
276 return std::unexpected{ std::forward<Err>(error) };
279#pragma region std::optional
283 template<
class Pred,
class Trans,
class Val>
284 requires std::predicate<Pred&, Val&> && std::invocable<Trans, Val>
286 return S_TransformOptIfImpl<false>(
287 std::forward<Pred>(pred),
288 std::forward<Trans>(trans),
289 std::forward<Val>(value)
294 template<auto Pred,
class Trans,
class Val>
295 requires std::predicate<
decltype(Pred), Val&> && std::invocable<Trans, Val>
297 return TransformOptIf<Pred>(ToValue<Pred>(), std::forward<Trans>(trans), std::forward<Val>(value));
301 template<auto Pred, auto Trans,
class Val>
302 requires std::invocable<
decltype(Trans), Val>
304 return TransformOptIf<Pred, Trans>(ToValue<Pred>(), ToValue<Trans>(), std::forward<Val>(value));
309 template<
class Pred,
class Trans,
class Val>
310 requires std::predicate<Pred&, Val&> && std::invocable<Trans, Val>
312 return S_TransformOptIfImpl<true>(
313 std::forward<Pred>(pred),
314 std::forward<Trans>(trans),
315 std::forward<Val>(value)
320 template<auto Pred,
class Trans,
class Val>
321 requires std::predicate<
decltype(Pred), Val&> && std::invocable<Trans, Val>
323 return TransformOptIfNot<Pred>(ToValue<Pred>(), std::forward<Trans>(trans), std::forward<Val>(value));
327 template<auto Pred, auto Trans,
class Val>
328 requires std::invocable<
decltype(Trans), Val>
330 return TransformOptIfNot<Pred, Trans>(ToValue<Pred>(), ToValue<Trans>(), std::forward<Val>(value));
334 template<
class Pred,
class Trans>
336 return [pred = std::forward<Pred>(pred),
337 trans = std::forward<Trans>(trans)](
auto&& value) {
338 return TransformOptIf(pred, trans, std::forward<
decltype(value)>(value));
343 template<auto Pred,
class Trans>
345 return [trans = std::forward<Trans>(trans)](
auto&& value) {
346 return TransformOptIf<Pred>(ToValue<Pred>(), trans, std::forward<
decltype(value)>(value));
351 template<auto Pred, auto Trans>
353 return TransformOptIfHof<Pred, Trans>(ToValue<Pred>(), ToValue<Trans>());
357 template<
class Pred,
class Trans>
359 return [pred = std::forward<Pred>(pred),
360 trans = std::forward<Trans>(trans)](
auto&& value) {
366 template<auto Pred,
class Trans>
368 return [trans = std::forward<Trans>(trans)](
auto&& value) {
369 return TransformOptIfNot<Pred>(ToValue<Pred>(), trans, std::forward<
decltype(value)>(value));
374 template<auto Pred, auto Trans>
376 return TransformOptIfNotHof<Pred, Trans>(ToValue<Pred>(), ToValue<Trans>());
380#pragma region std::expected
384 template<
class Pred,
class Trans,
class Val,
class Err>
385 requires std::predicate<Pred&, Val&> && std::invocable<Trans, Val>
386 constexpr auto TransformExpIf(Pred&& pred, Trans&& trans, Val&& value, Err&& error) {
387 return S_TransformExpIfImpl<false>(
388 std::forward<Pred>(pred),
389 std::forward<Trans>(trans),
390 std::forward<Val>(value),
391 std::forward<Err>(error)
396 template<auto Pred,
class Trans,
class Val,
class Err>
397 requires std::predicate<
decltype(Pred), Val&> && std::invocable<Trans, Val>
399 return S_TransformExpIfImpl<false>(
401 std::forward<Trans>(trans),
402 std::forward<Val>(value),
403 std::forward<Err>(error)
408 template<auto Pred, auto Trans,
class Val,
class Err>
409 requires std::invocable<
decltype(Trans), Val>
411 return S_TransformExpIfImpl<false>(
414 std::forward<Val>(value),
415 std::forward<Err>(error)
420 template<
class Pred,
class Trans,
class Val,
class Err>
421 requires std::predicate<Pred&, Val&> && std::invocable<Trans, Val>
423 return S_TransformExpIfImpl<true>(
424 std::forward<Pred>(pred),
425 std::forward<Trans>(trans),
426 std::forward<Val>(value),
427 std::forward<Err>(error)
432 template<auto Pred,
class Trans,
class Val,
class Err>
433 requires std::predicate<
decltype(Pred), Val&> && std::invocable<Trans, Val>
435 return S_TransformExpIfImpl<true>(
437 std::forward<Trans>(trans),
438 std::forward<Val>(value),
439 std::forward<Err>(error)
444 template<auto Pred, auto Trans,
class Val,
class Err>
445 requires std::invocable<
decltype(Trans), Val>
447 return S_TransformExpIfImpl<true>(
450 std::forward<Val>(value),
451 std::forward<Err>(error)
456 template<
class Pred,
class Trans,
class Err>
458 return [pred = std::forward<Pred>(pred),
459 trans = std::forward<Trans>(trans),
460 error = std::forward<Err>(error)](
auto&& value) {
461 return TransformExpIf(pred, trans, std::forward<
decltype(value)>(value), error);
466 template<auto Pred,
class Trans,
class Err>
468 return [trans = std::forward<Trans>(trans),
469 error = std::forward<Err>(error)](
auto&& value) {
470 return TransformExpIf(ToValue<Pred>(), trans, std::forward<
decltype(value)>(value), error);
475 template<auto Pred, auto Trans,
class Err>
477 return TransformExpIfHof(ToValue<Pred>(), ToValue<Trans>(), std::forward<Err>(error));
481 template<
class Pred,
class Trans,
class Err>
483 return [pred = std::forward<Pred>(pred),
484 trans = std::forward<Trans>(trans),
485 error = std::forward<Err>(error)](
auto&& value) {
486 return TransformExpIfNot(pred, trans, std::forward<
decltype(value)>(value), error);
491 template<auto Pred,
class Trans,
class Err>
493 return [trans = std::forward<Trans>(trans),
494 error = std::forward<Err>(error)](
auto&& value) {
495 return TransformExpIfNot(ToValue<Pred>(), trans, std::forward<
decltype(value)>(value), error);
500 template<auto Pred, auto Trans,
class Err>
508#pragma region NulloptIf/Not
510 template<
bool Negate,
class Pred,
class Val>
511 requires std::predicate<Pred&, Val&>
512 constexpr std::optional<std::remove_cvref_t<Val>>
514 if (!S_TestIf<Negate>(pred, value))
515 return std::forward<Val>(value);
520 template<
class Pred,
class Val>
522 return S_NulloptIfImpl<false>(
523 std::forward<Pred>(pred),
524 std::forward<Val>(value)
529 template<auto Pred,
class Val>
531 return NulloptIf(ToValue<Pred>(), std::forward<Val>(value));
535 template<
class Pred,
class Val>
537 return S_NulloptIfImpl<true>(
538 std::forward<Pred>(pred),
539 std::forward<Val>(value)
544 template<auto Pred,
class Val>
546 return NulloptIfNot(ToValue<Pred>(), std::forward<Val>(value));
552 return [pred = std::forward<Pred>(pred)](
auto&& value) {
553 return NulloptIf(pred, std::forward<
decltype(value)>(value));
560 return NulloptIfHof<Pred>(
ToValue(Pred));
566 return [pred = std::forward<Pred>(pred)](
auto&& value) {
567 return NulloptIfNot(pred, std::forward<
decltype(value)>(value));
574 return NulloptIfNotHof<Pred>(ToValue<Pred>());
579#pragma region WhileNotFail
585 template<std::ranges::input_range R,
class F,
class Acc,
586 class Exp = std::iter_value_t<R>,
class Val = Exp::value_type,
class Err = Exp::error_type>
587 requires std::same_as<Exp, std::expected<Val, Err>>
588 && std::invocable<F, Acc, Val> && std::same_as<Acc, std::invoke_result_t<F, Acc, Val>>
589 constexpr std::expected<std::remove_cvref_t<Acc>, std::remove_cvref_t<Err>>
592 using AccT = std::remove_cvref_t<Acc>;
593 using ValT = std::remove_cvref_t<Val>;
594 using ErrT = std::remove_cvref_t<Err>;
596 AccT accumulator = std::forward<Acc>(initial);
598 for (
auto&& val : range) {
600 return std::unexpected{ val.error() };
602 accumulator = std::invoke(callable, std::forward<Acc>(accumulator), *val);
609 template<
class F,
class Exp>
611 return [callable = std::forward<F>(callable), reducer = std::forward<Exp>(reducer)]
612 <std::ranges::input_range R>(R&& range){
613 return FoldWhileSuccess(std::forward<R>(range), std::forward<F>(callable), std::forward<Exp>(reducer));
620 template<
class T,
class F>
621 requires std::invocable<F, T>
622 constexpr auto Self(T&& val, F&& callable) {
623 std::invoke(std::forward<F>(callable), val);
624 return std::forward<T>(val);
629 return [callable = std::forward<F>(callable)]<
class T>(T&& val) {
630 return Self(std::forward<F>(callable), std::forward<T>(val));
constexpr auto CallIfErrorHof()
@hof{CallIfError}
Definition Functional.hpp:144
constexpr std::expected< Val, std::decay_t< Err > > S_ErrorIfImpl(Pred &&pred, Val &&value, Err &&error)
Definition Functional.hpp:184
constexpr auto TransformExpIfHof(Pred &&pred, Trans &&trans, Err &&error)
@hof{TransformExpIf}
Definition Functional.hpp:457
constexpr auto FoldWhileSuccessHof(F &&callable, Exp &&reducer={})
@hof{FoldWhileSuccess}
Definition Functional.hpp:610
constexpr auto Const(Ret(Class::*ptr)(Args...) const)
Definition Functional.hpp:22
constexpr auto TransformOptIfHof()
@hof{TransformOptIf}
Definition Functional.hpp:352
constexpr auto ErrorIf(Pred &&pred, Val &&value, Err &&error)
In a std::expected<Val, Err> context, transform an error into a value only if the predicate match.
Definition Functional.hpp:192
constexpr auto ToValue()
If the template parameter is a value, then returns it. If is a type then construct and returns it.
Definition Functional.hpp:13
constexpr auto NulloptIfHof()
@hof{NulloptIf}
Definition Functional.hpp:559
constexpr auto ErrorIfNotHof(Pred &&pred, Err &&error)
@hof{ErrorIfNof}
Definition Functional.hpp:240
constexpr std::optional< std::remove_cvref_t< Val > > S_NulloptIfImpl(Pred &&pred, Val &&value)
Definition Functional.hpp:513
constexpr auto ValueOrHof(Err &&err)
@hof{ValueOr}
Definition Functional.hpp:50
constexpr std::expected< std::remove_cvref_t< Acc >, std::remove_cvref_t< Err > > FoldWhileSuccess(R &&range, F &&callable, Acc &&initial={})
fast fail foldr
Definition Functional.hpp:590
constexpr auto TransformExpIfNot(Pred &&pred, Trans &&trans, Val &&value, Err &&error)
In the std::expected<Val, Err> context, returns the transformation applied to the value if the predic...
Definition Functional.hpp:422
constexpr auto TransformExpIf(Pred &&pred, Trans &&trans, Val &&value, Err &&error)
In the std::expected<Val, Err> context, returns the transformation applied to the value if the predic...
Definition Functional.hpp:386
constexpr std::expected< typename std::remove_cvref_t< Opt >::value_type, Err > ValueOr(Opt &&val, Err &&err)
Monad friendly function to transform std::expected<std::optional<T>, Err> into std::expected<T,...
Definition Functional.hpp:38
constexpr std::expected< Val, std::invoke_result_t< Trans, Val > > S_CallIfErrorImpl(Pred &&pred, Trans &&trans, Val &&value)
Definition Functional.hpp:73
constexpr auto ConstFn(Ret(Class::*ptr)(Args...) const)
Definition Functional.hpp:27
constexpr auto MutFn(Ret(Class::*ptr)(Args...))
Definition Functional.hpp:29
constexpr auto S_TransformOptIfImpl(Pred &&pred, Trans &&trans, Val &&value) -> std::optional< std::invoke_result_t< Trans, Val > >
Definition Functional.hpp:261
constexpr auto SelfHof(F &&callable)
Definition Functional.hpp:628
constexpr auto TransformOptIfNot(Pred &&pred, Trans &&trans, Val &&value)
In the std::optional<Val> context, returns the transformation applied to the value if the predicate d...
Definition Functional.hpp:311
constexpr auto NulloptIfNotHof()
@hof{NulloptIfNot}
Definition Functional.hpp:573
constexpr auto ErrorIfNot(Pred &&pred, Val &&value, Err &&error)
In a std::expected<Val, Err> context, transform an error into a value only if the predicate doesn't m...
Definition Functional.hpp:208
constexpr auto CallIfErrorNot(Pred &&pred, Trans &&trans, Val &&value)
In the std::expected<Val, Err> context, returns the value if the predicate doesn't match,...
Definition Functional.hpp:105
constexpr bool S_TestIfImpl(Pred &&pred, Val &value)
Definition Functional.hpp:177
constexpr auto TransformOptIf(Pred &&pred, Trans &&trans, Val &&value)
In the std::optional<Val> context, returns the transformation applied to the value if the predicate m...
Definition Functional.hpp:285
constexpr auto ErrorIfHof(Pred &&pred, Err &&error)
@hof{ErrorIf}
Definition Functional.hpp:224
constexpr auto Mut(Ret(Class::*ptr)(Args...))
Definition Functional.hpp:24
constexpr auto CallIfErrorNotHof()
@hof{CallIfErrorNot}
Definition Functional.hpp:167
constexpr auto CallIfError(Pred &&pred, Trans &&trans, Val &&value)
In the std::expected<Val, Err> context, returns the value if the predicate match, or the std::unexpec...
Definition Functional.hpp:82
constexpr auto S_TransformExpIfImpl(Pred &&pred, Trans &&trans, Val &&value, Err &&error) -> std::expected< std::invoke_result_t< Trans, Val >, std::decay_t< Err > >
Definition Functional.hpp:271
constexpr auto NulloptIf(Pred &&pred, Val &&value)
In a std::optional<T> context, transforms the value to std::nullopt if the predicate match.
Definition Functional.hpp:521
constexpr auto TransformOptIfNotHof()
@hof{TransformOptIfNot}
Definition Functional.hpp:375
constexpr auto NulloptIfNot(Pred &&pred, Val &&value)
In a std::optional<T> context, transforms the value to std::nullopt if the predicate doesn't match.
Definition Functional.hpp:536
constexpr auto TransformExpIfNotHof(Pred &&pred, Trans &&trans, Err &&error)
@hof{TransformExpIfNot}
Definition Functional.hpp:482
constexpr auto Self(T &&val, F &&callable)
Definition Functional.hpp:622