Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Optional.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/Containers/Adapters/Adder.h"
6#include "Stroika/Foundation/Execution/Common.h"
7#include "Stroika/Foundation/Execution/Throw.h"
8
9namespace Stroika::Foundation::Memory {
10
11 /*
12 ********************************************************************************
13 ************************ OptionalFromNullable **********************************
14 ********************************************************************************
15 */
16 template <typename RHS_CONVERTIBLE_TO_OPTIONAL_OF_T, constructible_from<RHS_CONVERTIBLE_TO_OPTIONAL_OF_T> T>
17 constexpr optional<T> OptionalFromNullable (const RHS_CONVERTIBLE_TO_OPTIONAL_OF_T* from)
18 {
19 return from == nullptr ? nullopt : optional<T>{static_cast<T> (*from)};
20 }
21
22 /*
23 ********************************************************************************
24 ******************************** AccumulateIf **********************************
25 ********************************************************************************
26 */
27 template <typename T, convertible_to<T> CONVERTIBLE_TO_T, convertible_to<function<T (T, T)>> OP>
28 void AccumulateIf (optional<T>* lhsOptionalValue, const optional<CONVERTIBLE_TO_T>& rhsOptionalValue, const OP& op)
29 {
30 RequireNotNull (lhsOptionalValue);
31 if (lhsOptionalValue->has_value ()) {
32 if (rhsOptionalValue.has_value ()) {
33 *lhsOptionalValue = op (**lhsOptionalValue, static_cast<T> (*rhsOptionalValue));
34 }
35 }
36 else if (rhsOptionalValue.has_value ()) {
37 *lhsOptionalValue = static_cast<T> (*rhsOptionalValue);
38 }
39 }
40 template <typename T, convertible_to<function<T (T, T)>> OP>
41 inline void AccumulateIf (optional<T>* lhsOptionalValue, const T& rhsValue, const OP& op)
42 {
43 RequireNotNull (lhsOptionalValue);
44 if (lhsOptionalValue->has_value ()) {
45 *lhsOptionalValue = op (**lhsOptionalValue, rhsValue);
46 }
47 else {
48 *lhsOptionalValue = rhsValue;
49 }
50 }
51 template <typename T, template <typename> typename CONTAINER>
52 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
53 void AccumulateIf (optional<CONTAINER<T>>* lhsOptionalValue, const optional<T>& rhsOptionalValue)
54 {
55 RequireNotNull (lhsOptionalValue);
56 if (rhsOptionalValue.has_value ()) {
57 if (not lhsOptionalValue->has_value ()) {
58 *lhsOptionalValue = CONTAINER<T>{};
59 }
60 Containers::Adapters::Adder<CONTAINER<T>>::Add (&**lhsOptionalValue, *rhsOptionalValue);
61 }
62 }
63 template <typename T, template <typename> typename CONTAINER>
64 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
65 void AccumulateIf (optional<CONTAINER<T>>* lhsOptionalValue, const T& rhsValue)
66 {
67 RequireNotNull (lhsOptionalValue);
68 if (not lhsOptionalValue->has_value ()) {
69 *lhsOptionalValue = CONTAINER<T>{};
70 }
71 Containers::Adapters::Adder<CONTAINER<T>>::Add (&**lhsOptionalValue, rhsValue);
72 }
73 template <typename T, convertible_to<T> CONVERTIBLE_TO_T, convertible_to<function<T (T, T)>> OP>
74 inline optional<T> AccumulateIf (const optional<T>& lhsOptionalValue, const optional<CONVERTIBLE_TO_T>& rhsOptionalValue, const OP& op)
75 {
76 optional<T> result{lhsOptionalValue};
77 AccumulateIf (&result, rhsOptionalValue, op);
78 return result;
79 }
80 template <typename T, convertible_to<function<T (T, T)>> OP>
81 inline optional<T> AccumulateIf (const optional<T>& lhsOptionalValue, const T& rhsValue, const OP& op)
82 {
83 optional<T> result{lhsOptionalValue};
84 AccumulateIf (&result, rhsValue, op);
85 return result;
86 }
87 template <typename T, template <typename> typename CONTAINER>
88 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
89 optional<CONTAINER<T>> AccumulateIf (const optional<CONTAINER<T>>& lhsOptionalValue, const optional<T>& rhsOptionalValue)
90 {
91 optional<T> result{lhsOptionalValue};
92 AccumulateIf (&result, rhsOptionalValue);
93 return result;
94 }
95 template <typename T, template <typename> typename CONTAINER>
96 requires (is_convertible_v<typename Containers::Adapters::Adder<CONTAINER<T>>::value_type, T>)
97 optional<CONTAINER<T>> AccumulateIf (const optional<CONTAINER<T>>& lhsOptionalValue, const T& rhsValue)
98 {
99 optional<T> result{lhsOptionalValue};
100 AccumulateIf (&result, rhsValue);
101 return result;
102 }
103
104 /*
105 ********************************************************************************
106 ************************************ CopyToIf **********************************
107 ********************************************************************************
108 */
109 template <typename T, typename CONVERTABLE_TO_TYPE>
110 inline void CopyToIf (CONVERTABLE_TO_TYPE* to, const optional<T>& copyFromIfHasValue)
111 {
112 if (copyFromIfHasValue) {
113 // explicit cast to silence compiler warnings - use of CopyToIf() is fairly explicit about doing the needed conversions and
114 // offers no other direct way to silence the warnings
115 *to = static_cast<CONVERTABLE_TO_TYPE> (*copyFromIfHasValue);
116 }
117 }
118 template <typename T, typename CONVERTABLE_TO_OPTIONAL_OF_TYPE>
119 inline void CopyToIf (optional<CONVERTABLE_TO_OPTIONAL_OF_TYPE>* to, const optional<T>& copyFromIfHasValue)
120 {
121 if (copyFromIfHasValue) {
122 // explicit cast to silence compiler warnings - use of CopyToIf() is fairly explicit about doing the needed conversions and
123 // offers no other direct way to silence the warnings
124 *to = static_cast<CONVERTABLE_TO_OPTIONAL_OF_TYPE> (*copyFromIfHasValue);
125 }
126 }
127
128 /*
129 ********************************************************************************
130 ********************************* NullCoalesce *********************************
131 ********************************************************************************
132 */
133 template <Private_::INullCoalescable OT>
134 inline const OT& NullCoalesce (const OT& l, const OT& r)
135 {
136 if (l) {
137 return l;
138 }
139 return r;
140 }
141 template <Private_::INullCoalescable OT, convertible_to<const Private_::OptionalType2ValueType<OT>&> DEFAULT_TYPE>
142 inline const Private_::OptionalType2ValueType<OT>& NullCoalesce (const OT& l, const DEFAULT_TYPE& r)
143 {
144 if (l) {
145 return *l;
146 }
147 return r;
148 }
149
150 /*
151 ********************************************************************************
152 ************************************ ValueOf ***********************************
153 ********************************************************************************
154 */
155 template <typename T>
156 constexpr const T& ValueOf (const optional<T>& t)
157 {
158 Require (t);
159 return *t;
160 }
161
162 /*
163 ********************************************************************************
164 ******************************** ValueOfOrThrow ********************************
165 ********************************************************************************
166 */
167 template <typename T, typename EXCEPT>
168 inline const T& ValueOfOrThrow (const optional<T>& t, const EXCEPT& throwIfNull)
169 {
170 Execution::ThrowIfNull (t, throwIfNull);
171 return *t;
172 }
173
174 /*
175 ********************************************************************************
176 ******************************** OptionallyCopy ********************************
177 ********************************************************************************
178 */
179 template <typename OUT_T, Common::explicitly_convertible_to<OUT_T> IN_T>
180 inline optional<OUT_T> OptionallyCopy (const optional<IN_T>& in)
181 {
182 if (in) {
183 return OUT_T{*in};
184 }
185 return nullopt;
186 }
187 template <typename OUT_T, typename IN_T, invocable<IN_T> IN_TO_OUT_CONVERTER>
188 inline optional<OUT_T> OptionallyCopy (const optional<IN_T>& in, IN_TO_OUT_CONVERTER&& cvt)
189 requires (convertible_to<invoke_result_t<IN_TO_OUT_CONVERTER, IN_T>, optional<OUT_T>>)
190 {
191 if (in) {
192 return forward<IN_TO_OUT_CONVERTER> (cvt) (*in);
193 }
194 return nullopt;
195 }
196
197 /*
198 ********************************************************************************
199 ************************************ operator+ *********************************
200 ********************************************************************************
201 */
202 template <typename T>
203 inline optional<T> operator+ (const optional<T>& lhs, const optional<T>& rhs)
204 {
205 if (lhs and rhs) {
206 return *lhs + *rhs;
207 }
208 return nullopt;
209 }
210 template <typename T>
211 inline optional<T> operator+ (const optional<T>& lhs, const T& rhs)
212 {
213 if (lhs) {
214 return (*lhs) + rhs;
215 }
216 return nullopt;
217 }
218 template <typename T>
219 inline optional<T> operator+ (const T& lhs, const optional<T>& rhs)
220 {
221 if (rhs) {
222 return lhs + (*rhs);
223 }
224 return nullopt;
225 }
226
227 /*
228 ********************************************************************************
229 ************************************ operator- *********************************
230 ********************************************************************************
231 */
232 template <typename T>
233 inline optional<T> operator- (const optional<T>& lhs, const optional<T>& rhs)
234 {
235 if (lhs and rhs) {
236 return *lhs - *rhs;
237 }
238 return nullopt;
239 }
240 template <typename T>
241 inline optional<T> operator- (const optional<T>& lhs, const T& rhs)
242 {
243 if (lhs) {
244 return (*lhs) - rhs;
245 }
246 return nullopt;
247 }
248 template <typename T>
249 inline optional<T> operator- (const T& lhs, const optional<T>& rhs)
250 {
251 if (rhs) {
252 return lhs - (*rhs);
253 }
254 return nullopt;
255 }
256
257 /*
258 ********************************************************************************
259 ************************************ operator* *********************************
260 ********************************************************************************
261 */
262 template <typename T>
263 inline optional<T> operator* (const optional<T>& lhs, const optional<T>& rhs)
264 {
265 if (lhs and rhs) {
266 return (*lhs) * (*rhs);
267 }
268 return nullopt;
269 }
270 template <typename T>
271 inline optional<T> operator* (const optional<T>& lhs, const T& rhs)
272 {
273 if (lhs) {
274 return (*lhs) * rhs;
275 }
276 return nullopt;
277 }
278 template <typename T>
279 inline optional<T> operator* (const T& lhs, const optional<T>& rhs)
280 {
281 if (rhs) {
282 return lhs * (*rhs);
283 }
284 return nullopt;
285 }
286
287 /*
288 ********************************************************************************
289 ************************************ operator/ *********************************
290 ********************************************************************************
291 */
292 template <typename T>
293 inline optional<T> operator/ (const optional<T>& lhs, const optional<T>& rhs)
294 {
295 if (lhs) {
296 return (*lhs) / rhs;
297 }
298 }
299 template <typename T>
300 inline optional<T> operator/ (const optional<T>& lhs, const T& rhs)
301 {
302 if (lhs) {
303 return (*lhs) / rhs;
304 }
305 return nullopt;
306 }
307 template <typename T>
308 inline optional<T> operator/ (const T& lhs, const optional<T>& rhs)
309 {
310 if (rhs) {
311 return lhs / (*rhs);
312 }
313 return nullopt;
314 }
315
316}
#define RequireNotNull(p)
Definition Assertions.h:347
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_...
Definition Optional.inl:180
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-...
Definition Optional.inl:134
constexpr optional< T > OptionalFromNullable(const RHS_CONVERTIBLE_TO_OPTIONAL_OF_T *from)
Definition Optional.inl:17
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...
Definition Optional.inl:28
constexpr const T & ValueOf(const optional< T > &t)
Same as *t, but Requires that 't' is engaged.
Definition Optional.inl:156
void CopyToIf(CONVERTABLE_TO_TYPE *to, const optional< T > &copyFromIfHasValue)
Definition Optional.inl:110
void ThrowIfNull(const Private_::ConstVoidStar &p, const HRESULT &hr)
Template specialization for ThrowIfNull (), for thing being thrown HRESULT - really throw HRESULTErro...