4#ifndef _Stroika_Foundation_Memory_Optional_h_
5#define _Stroika_Foundation_Memory_Optional_h_ 1
7#include "Stroika/Foundation/StroikaPreComp.h"
11#include <shared_mutex>
13#include "Stroika/Foundation/Common/Common.h"
15#include "Stroika/Foundation/Common/Concepts.h"
17#include "Stroika/Foundation/Containers/Adapters/Adder.h"
19#include "Stroika/Foundation/Execution/NullMutex.h"
21#include "Stroika/Foundation/Memory/Common.h"
39namespace Stroika::Foundation::Memory {
79 template <
typename T, convertible_to<T> CONVERTIBLE_TO_T, convertible_to<function<T (T, T)>> OP = plus<T>>
80 void AccumulateIf (optional<T>* lhsOptionalValue,
const optional<CONVERTIBLE_TO_T>& rhsOptionalValue,
const OP& op = OP{});
81 template <
typename T, convertible_to<function<T (T, T)>> OP = plus<T>>
82 void AccumulateIf (optional<T>* lhsOptionalValue,
const T& rhsValue,
const OP& op = OP{});
83 template <
typename T,
template <
typename>
typename CONTAINER>
84 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
85 void AccumulateIf (optional<CONTAINER<T>>* lhsOptionalValue,
const optional<T>& rhsOptionalValue);
86 template <
typename T,
template <
typename>
typename CONTAINER>
87 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
88 void AccumulateIf (optional<CONTAINER<T>>* lhsOptionalValue,
const T& rhsValue);
89 template <
typename T, convertible_to<T> CONVERTIBLE_TO_T, convertible_to<function<T (T, T)>> OP = plus<T>>
90 optional<T>
AccumulateIf (
const optional<T>& lhsOptionalValue,
const optional<CONVERTIBLE_TO_T>& rhsOptionalValue,
const OP& op = OP{});
91 template <
typename T, convertible_to<function<T (T, T)>> OP = plus<T>>
92 optional<T>
AccumulateIf (
const optional<T>& lhsOptionalValue,
const T& rhsValue,
const OP& op = OP{});
93 template <
typename T,
template <
typename>
typename CONTAINER>
94 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
95 optional<CONTAINER<T>> AccumulateIf (
const optional<CONTAINER<T>>& lhsOptionalValue,
const optional<T>& rhsOptionalValue);
96 template <
typename T,
template <
typename>
typename CONTAINER>
97 optional<CONTAINER<T>>
AccumulateIf (
const optional<CONTAINER<T>>& lhsOptionalValue,
const T& rhsValue);
127 template <
typename T,
typename CONVERTABLE_TO_TYPE>
128 void CopyToIf (CONVERTABLE_TO_TYPE* to,
const optional<T>& copyFromIfHasValue);
129 template <
typename T,
typename CONVERTABLE_TO_OPTIONAL_OF_TYPE>
130 void CopyToIf (optional<CONVERTABLE_TO_OPTIONAL_OF_TYPE>* to,
const optional<T>& copyFromIfHasValue);
133 template <
typename T>
134 concept INullCoalescable =
requires (T t) {
135 static_cast<bool> (t);
138 template <
typename OT>
139 using OptionalType2ValueType = remove_cvref_t<decltype (*declval<OT> ())>;
166 template <Private_::INullCoalescable OT>
168 template <Private_::INullCoalescable OT, convertible_to<const Private_::OptionalType2ValueType<OT>&> DEFAULT_TYPE = Private_::OptionalType2ValueType<OT>>
169 const Private_::OptionalType2ValueType<OT>&
NullCoalesce (
const OT& l,
const DEFAULT_TYPE& r = DEFAULT_TYPE{});
177 template <
typename T>
178 constexpr const T&
ValueOf (
const optional<T>& t);
182 template <
typename T,
typename EXCEPT = bad_optional_access>
183 const T& ValueOfOrThrow (
const optional<T>& t,
const EXCEPT& throwIfNull = {});
197 template <
typename OUT_T, Common::explicitly_convertible_to<OUT_T> IN_T>
199 template <
typename OUT_T,
typename IN_T, invocable<IN_T> IN_TO_OUT_CONVERTER>
200 optional<OUT_T>
OptionallyCopy (
const optional<IN_T>& in, IN_TO_OUT_CONVERTER&& cvt)
201 requires (convertible_to<invoke_result_t<IN_TO_OUT_CONVERTER, IN_T>, optional<OUT_T>>);
206 template <
typename T,
class F>
207 constexpr auto And_Then (
const optional<T>& o, F&& f)
209#if __cplusplus > 202302L || _HAS_CXX23 || (_LIBCPP_STD_VER >= 23)
210 return o.and_then (forward<F> (f));
212 if (o.has_value ()) {
213 return std::invoke (std::forward<F> (f), *o);
216 return std::remove_cvref_t<std::invoke_result_t<F, T>>{};
223 template <
typename T,
class F>
224 constexpr auto Or_Else (
const optional<T>& o, F&& f)
226#if __cplusplus > 202302L || _HAS_CXX23 || (_LIBCPP_STD_VER >= 23)
227 return o.or_else (forward<F> (f));
229 if (o.has_value ()) {
233 return forward<F> (f) ();
240 template <
typename T,
class F>
243#if __cplusplus > 202302L || _HAS_CXX23 || (_LIBCPP_STD_VER >= 23)
244 return o.transform (forward<F> (f));
246 using U = std::remove_cv_t<std::invoke_result_t<F, T>>;
247 if (o.has_value ()) {
248 return optional<U>{forward<F> (f) (*o)};
251 return optional<U>{};
269 template <
typename RHS_CONVERTIBLE_TO_OPTIONAL_OF_T, constructible_from<RHS_CONVERTIBLE_TO_OPTIONAL_OF_T> T = RHS_CONVERTIBLE_TO_OPTIONAL_OF_T>
270 constexpr optional<T> OptionalFromNullable (
const RHS_CONVERTIBLE_TO_OPTIONAL_OF_T* from);
278 template <
typename T>
279 optional<T> operator+ (
const optional<T>& lhs,
const optional<T>& rhs);
280 template <
typename T>
281 optional<T> operator+ (
const optional<T>& lhs,
const T& rhs);
282 template <
typename T>
283 optional<T> operator+ (
const T& lhs,
const optional<T>& rhs);
291 template <
typename T>
292 optional<T> operator- (
const optional<T>& lhs,
const optional<T>& rhs);
293 template <
typename T>
294 optional<T> operator- (
const optional<T>& lhs,
const T& rhs);
295 template <
typename T>
296 optional<T> operator- (
const T& lhs,
const optional<T>& rhs);
304 template <
typename T>
305 optional<T> operator* (
const optional<T>& lhs,
const optional<T>& rhs);
306 template <
typename T>
307 optional<T> operator* (
const optional<T>& lhs,
const T& rhs);
308 template <
typename T>
309 optional<T> operator* (
const T& lhs,
const optional<T>& rhs);
317 template <
typename T>
318 optional<T> operator/ (
const optional<T>& lhs,
const optional<T>& rhs);
319 template <
typename T>
320 optional<T> operator/ (
const optional<T>& lhs,
const T& rhs);
321 template <
typename T>
322 optional<T> operator/ (
const T& lhs,
const optional<T>& rhs);
331#include "Optional.inl"
optional< OUT_T > OptionallyCopy(const optional< IN_T > &in)
if you can copy an IN_T to an OUT_T, you should be able to copy an optional<IN_T> to an optional<OUT_...
constexpr auto And_Then(const optional< T > &o, F &&f)
const OT & NullCoalesce(const OT &l, const OT &r)
return one of l, or r, with first preference for which is engaged, and second preference for left-to-...
constexpr auto Or_Else(const optional< T > &o, F &&f)
constexpr auto Transform(const optional< T > &o, F &&f)
void AccumulateIf(optional< T > *lhsOptionalValue, const optional< CONVERTIBLE_TO_T > &rhsOptionalValue, const OP &op=OP{})
AccumulateIf () add in the rhs argument value to lhs optional, but if both were missing leave 'lhs' a...
constexpr const T & ValueOf(const optional< T > &t)
Same as *t, but Requires that 't' is engaged.
void CopyToIf(CONVERTABLE_TO_TYPE *to, const optional< T > ©FromIfHasValue)