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"
20#include "Stroika/Foundation/Memory/Common.h"
38namespace Stroika::Foundation::Memory {
78 template <
typename T, convertible_to<T> CONVERTIBLE_TO_T, convertible_to<function<T (T, T)>> OP = plus<T>>
79 void AccumulateIf (optional<T>* lhsOptionalValue,
const optional<CONVERTIBLE_TO_T>& rhsOptionalValue,
const OP& op = OP{});
80 template <
typename T, convertible_to<function<T (T, T)>> OP = plus<T>>
81 void AccumulateIf (optional<T>* lhsOptionalValue,
const T& rhsValue,
const OP& op = OP{});
82 template <
typename T,
template <
typename>
typename CONTAINER>
83 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
84 void AccumulateIf (optional<CONTAINER<T>>* lhsOptionalValue,
const optional<T>& rhsOptionalValue);
85 template <
typename T,
template <
typename>
typename CONTAINER>
86 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
87 void AccumulateIf (optional<CONTAINER<T>>* lhsOptionalValue,
const T& rhsValue);
88 template <
typename T, convertible_to<T> CONVERTIBLE_TO_T, convertible_to<function<T (T, T)>> OP = plus<T>>
89 optional<T>
AccumulateIf (
const optional<T>& lhsOptionalValue,
const optional<CONVERTIBLE_TO_T>& rhsOptionalValue,
const OP& op = OP{});
90 template <
typename T, convertible_to<function<T (T, T)>> OP = plus<T>>
91 optional<T>
AccumulateIf (
const optional<T>& lhsOptionalValue,
const T& rhsValue,
const OP& op = OP{});
92 template <
typename T,
template <
typename>
typename CONTAINER>
93 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
94 optional<CONTAINER<T>> AccumulateIf (
const optional<CONTAINER<T>>& lhsOptionalValue,
const optional<T>& rhsOptionalValue);
95 template <
typename T,
template <
typename>
typename CONTAINER>
96 optional<CONTAINER<T>>
AccumulateIf (
const optional<CONTAINER<T>>& lhsOptionalValue,
const T& rhsValue);
126 template <
typename T,
typename CONVERTABLE_TO_TYPE>
127 constexpr void CopyToIf (CONVERTABLE_TO_TYPE* to,
const optional<T>& copyFromIfHasValue);
128 template <
typename T,
typename CONVERTABLE_TO_OPTIONAL_OF_TYPE>
129 constexpr void CopyToIf (optional<CONVERTABLE_TO_OPTIONAL_OF_TYPE>* to,
const optional<T>& copyFromIfHasValue);
132 template <
typename T>
133 concept INullCoalescable =
requires (T t) {
134 static_cast<bool> (t);
137 template <
typename OT>
138 using OptionalType2ValueType = remove_cvref_t<decltype (*declval<OT> ())>;
165 template <Private_::INullCoalescable OT>
167 template <Private_::INullCoalescable OT, convertible_to<const Private_::OptionalType2ValueType<OT>&> DEFAULT_TYPE = Private_::OptionalType2ValueType<OT>>
168 const Private_::OptionalType2ValueType<OT>&
NullCoalesce (
const OT& l,
const DEFAULT_TYPE& r = DEFAULT_TYPE{});
176 template <
typename T>
177 constexpr const T&
ValueOf (
const optional<T>& t);
181 template <
typename T,
typename EXCEPT = bad_optional_access>
182 const T& ValueOfOrThrow (
const optional<T>& t,
const EXCEPT& throwIfNull = {});
196 template <
typename OUT_T, Common::explicitly_convertible_to<OUT_T> IN_T>
198 template <
typename OUT_T,
typename IN_T, invocable<IN_T> IN_TO_OUT_CONVERTER>
199 optional<OUT_T>
OptionallyCopy (
const optional<IN_T>& in, IN_TO_OUT_CONVERTER&& cvt)
200 requires (convertible_to<invoke_result_t<IN_TO_OUT_CONVERTER, IN_T>, optional<OUT_T>>);
205 template <
typename T,
class F>
206 constexpr auto And_Then (
const optional<T>& o, F&& f)
208#if __cplusplus > 202302L || _HAS_CXX23 || (_LIBCPP_STD_VER >= 23)
209 return o.and_then (forward<F> (f));
211 if (o.has_value ()) {
212 return std::invoke (std::forward<F> (f), *o);
215 return std::remove_cvref_t<std::invoke_result_t<F, T>>{};
222 template <
typename T,
class F>
223 constexpr auto Or_Else (
const optional<T>& o, F&& f)
225#if __cplusplus > 202302L || _HAS_CXX23 || (_LIBCPP_STD_VER >= 23)
226 return o.or_else (forward<F> (f));
228 if (o.has_value ()) {
232 return forward<F> (f) ();
239 template <
typename T,
class F>
242#if __cplusplus > 202302L || _HAS_CXX23 || (_LIBCPP_STD_VER >= 23)
243 return o.transform (forward<F> (f));
245 using U = std::remove_cv_t<std::invoke_result_t<F, T>>;
246 if (o.has_value ()) {
247 return optional<U>{forward<F> (f) (*o)};
250 return optional<U>{};
268 template <
typename RHS_CONVERTIBLE_TO_OPTIONAL_OF_T, constructible_from<RHS_CONVERTIBLE_TO_OPTIONAL_OF_T> T = RHS_CONVERTIBLE_TO_OPTIONAL_OF_T>
269 constexpr optional<T> OptionalFromNullable (
const RHS_CONVERTIBLE_TO_OPTIONAL_OF_T* from);
277 template <
typename T>
278 optional<T> operator+ (
const optional<T>& lhs,
const optional<T>& rhs);
279 template <
typename T>
280 optional<T> operator+ (
const optional<T>& lhs,
const T& rhs);
281 template <
typename T>
282 optional<T> operator+ (
const T& lhs,
const optional<T>& rhs);
290 template <
typename T>
291 optional<T> operator- (
const optional<T>& lhs,
const optional<T>& rhs);
292 template <
typename T>
293 optional<T> operator- (
const optional<T>& lhs,
const T& rhs);
294 template <
typename T>
295 optional<T> operator- (
const T& lhs,
const optional<T>& rhs);
303 template <
typename T>
304 optional<T> operator* (
const optional<T>& lhs,
const optional<T>& rhs);
305 template <
typename T>
306 optional<T> operator* (
const optional<T>& lhs,
const T& rhs);
307 template <
typename T>
308 optional<T> operator* (
const T& lhs,
const optional<T>& rhs);
316 template <
typename T>
317 optional<T> operator/ (
const optional<T>& lhs,
const optional<T>& rhs);
318 template <
typename T>
319 optional<T> operator/ (
const optional<T>& lhs,
const T& rhs);
320 template <
typename T>
321 optional<T> operator/ (
const T& lhs,
const optional<T>& rhs);
330#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 void CopyToIf(CONVERTABLE_TO_TYPE *to, const optional< T > ©FromIfHasValue)
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.