Mercurial > minori
comparison dep/toml11/toml/result.hpp @ 318:3b355fa948c7
config: use TOML instead of INI
unfortunately, INI is not enough, and causes some paths including
semicolons to break with our current storage of the library folders.
so, I decided to switch to TOML which does support real arrays...
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 12 Jun 2024 05:25:41 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
317:b1f4d1867ab1 | 318:3b355fa948c7 |
---|---|
1 // Copyright Toru Niina 2017. | |
2 // Distributed under the MIT License. | |
3 #ifndef TOML11_RESULT_HPP | |
4 #define TOML11_RESULT_HPP | |
5 #include "traits.hpp" | |
6 #include <type_traits> | |
7 #include <stdexcept> | |
8 #include <utility> | |
9 #include <new> | |
10 #include <string> | |
11 #include <sstream> | |
12 #include <cassert> | |
13 | |
14 namespace toml | |
15 { | |
16 | |
17 template<typename T> | |
18 struct success | |
19 { | |
20 using value_type = T; | |
21 value_type value; | |
22 | |
23 explicit success(const value_type& v) | |
24 noexcept(std::is_nothrow_copy_constructible<value_type>::value) | |
25 : value(v) | |
26 {} | |
27 explicit success(value_type&& v) | |
28 noexcept(std::is_nothrow_move_constructible<value_type>::value) | |
29 : value(std::move(v)) | |
30 {} | |
31 | |
32 template<typename U> | |
33 explicit success(U&& v): value(std::forward<U>(v)) {} | |
34 | |
35 template<typename U> | |
36 explicit success(const success<U>& v): value(v.value) {} | |
37 template<typename U> | |
38 explicit success(success<U>&& v): value(std::move(v.value)) {} | |
39 | |
40 ~success() = default; | |
41 success(const success&) = default; | |
42 success(success&&) = default; | |
43 success& operator=(const success&) = default; | |
44 success& operator=(success&&) = default; | |
45 }; | |
46 | |
47 template<typename T> | |
48 struct failure | |
49 { | |
50 using value_type = T; | |
51 value_type value; | |
52 | |
53 explicit failure(const value_type& v) | |
54 noexcept(std::is_nothrow_copy_constructible<value_type>::value) | |
55 : value(v) | |
56 {} | |
57 explicit failure(value_type&& v) | |
58 noexcept(std::is_nothrow_move_constructible<value_type>::value) | |
59 : value(std::move(v)) | |
60 {} | |
61 | |
62 template<typename U> | |
63 explicit failure(U&& v): value(std::forward<U>(v)) {} | |
64 | |
65 template<typename U> | |
66 explicit failure(const failure<U>& v): value(v.value) {} | |
67 template<typename U> | |
68 explicit failure(failure<U>&& v): value(std::move(v.value)) {} | |
69 | |
70 ~failure() = default; | |
71 failure(const failure&) = default; | |
72 failure(failure&&) = default; | |
73 failure& operator=(const failure&) = default; | |
74 failure& operator=(failure&&) = default; | |
75 }; | |
76 | |
77 template<typename T> | |
78 success<typename std::remove_cv<typename std::remove_reference<T>::type>::type> | |
79 ok(T&& v) | |
80 { | |
81 return success< | |
82 typename std::remove_cv<typename std::remove_reference<T>::type>::type | |
83 >(std::forward<T>(v)); | |
84 } | |
85 template<typename T> | |
86 failure<typename std::remove_cv<typename std::remove_reference<T>::type>::type> | |
87 err(T&& v) | |
88 { | |
89 return failure< | |
90 typename std::remove_cv<typename std::remove_reference<T>::type>::type | |
91 >(std::forward<T>(v)); | |
92 } | |
93 | |
94 inline success<std::string> ok(const char* literal) | |
95 { | |
96 return success<std::string>(std::string(literal)); | |
97 } | |
98 inline failure<std::string> err(const char* literal) | |
99 { | |
100 return failure<std::string>(std::string(literal)); | |
101 } | |
102 | |
103 | |
104 template<typename T, typename E> | |
105 struct result | |
106 { | |
107 using value_type = T; | |
108 using error_type = E; | |
109 using success_type = success<value_type>; | |
110 using failure_type = failure<error_type>; | |
111 | |
112 result(const success_type& s): is_ok_(true) | |
113 { | |
114 auto tmp = ::new(std::addressof(this->succ)) success_type(s); | |
115 assert(tmp == std::addressof(this->succ)); | |
116 (void)tmp; | |
117 } | |
118 result(const failure_type& f): is_ok_(false) | |
119 { | |
120 auto tmp = ::new(std::addressof(this->fail)) failure_type(f); | |
121 assert(tmp == std::addressof(this->fail)); | |
122 (void)tmp; | |
123 } | |
124 result(success_type&& s): is_ok_(true) | |
125 { | |
126 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); | |
127 assert(tmp == std::addressof(this->succ)); | |
128 (void)tmp; | |
129 } | |
130 result(failure_type&& f): is_ok_(false) | |
131 { | |
132 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); | |
133 assert(tmp == std::addressof(this->fail)); | |
134 (void)tmp; | |
135 } | |
136 | |
137 template<typename U> | |
138 result(const success<U>& s): is_ok_(true) | |
139 { | |
140 auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); | |
141 assert(tmp == std::addressof(this->succ)); | |
142 (void)tmp; | |
143 } | |
144 template<typename U> | |
145 result(const failure<U>& f): is_ok_(false) | |
146 { | |
147 auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); | |
148 assert(tmp == std::addressof(this->fail)); | |
149 (void)tmp; | |
150 } | |
151 template<typename U> | |
152 result(success<U>&& s): is_ok_(true) | |
153 { | |
154 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); | |
155 assert(tmp == std::addressof(this->succ)); | |
156 (void)tmp; | |
157 } | |
158 template<typename U> | |
159 result(failure<U>&& f): is_ok_(false) | |
160 { | |
161 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); | |
162 assert(tmp == std::addressof(this->fail)); | |
163 (void)tmp; | |
164 } | |
165 | |
166 result& operator=(const success_type& s) | |
167 { | |
168 this->cleanup(); | |
169 this->is_ok_ = true; | |
170 auto tmp = ::new(std::addressof(this->succ)) success_type(s); | |
171 assert(tmp == std::addressof(this->succ)); | |
172 (void)tmp; | |
173 return *this; | |
174 } | |
175 result& operator=(const failure_type& f) | |
176 { | |
177 this->cleanup(); | |
178 this->is_ok_ = false; | |
179 auto tmp = ::new(std::addressof(this->fail)) failure_type(f); | |
180 assert(tmp == std::addressof(this->fail)); | |
181 (void)tmp; | |
182 return *this; | |
183 } | |
184 result& operator=(success_type&& s) | |
185 { | |
186 this->cleanup(); | |
187 this->is_ok_ = true; | |
188 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); | |
189 assert(tmp == std::addressof(this->succ)); | |
190 (void)tmp; | |
191 return *this; | |
192 } | |
193 result& operator=(failure_type&& f) | |
194 { | |
195 this->cleanup(); | |
196 this->is_ok_ = false; | |
197 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); | |
198 assert(tmp == std::addressof(this->fail)); | |
199 (void)tmp; | |
200 return *this; | |
201 } | |
202 | |
203 template<typename U> | |
204 result& operator=(const success<U>& s) | |
205 { | |
206 this->cleanup(); | |
207 this->is_ok_ = true; | |
208 auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); | |
209 assert(tmp == std::addressof(this->succ)); | |
210 (void)tmp; | |
211 return *this; | |
212 } | |
213 template<typename U> | |
214 result& operator=(const failure<U>& f) | |
215 { | |
216 this->cleanup(); | |
217 this->is_ok_ = false; | |
218 auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); | |
219 assert(tmp == std::addressof(this->fail)); | |
220 (void)tmp; | |
221 return *this; | |
222 } | |
223 template<typename U> | |
224 result& operator=(success<U>&& s) | |
225 { | |
226 this->cleanup(); | |
227 this->is_ok_ = true; | |
228 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); | |
229 assert(tmp == std::addressof(this->succ)); | |
230 (void)tmp; | |
231 return *this; | |
232 } | |
233 template<typename U> | |
234 result& operator=(failure<U>&& f) | |
235 { | |
236 this->cleanup(); | |
237 this->is_ok_ = false; | |
238 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); | |
239 assert(tmp == std::addressof(this->fail)); | |
240 (void)tmp; | |
241 return *this; | |
242 } | |
243 | |
244 ~result() noexcept {this->cleanup();} | |
245 | |
246 result(const result& other): is_ok_(other.is_ok()) | |
247 { | |
248 if(other.is_ok()) | |
249 { | |
250 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
251 assert(tmp == std::addressof(this->succ)); | |
252 (void)tmp; | |
253 } | |
254 else | |
255 { | |
256 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
257 assert(tmp == std::addressof(this->fail)); | |
258 (void)tmp; | |
259 } | |
260 } | |
261 result(result&& other): is_ok_(other.is_ok()) | |
262 { | |
263 if(other.is_ok()) | |
264 { | |
265 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
266 assert(tmp == std::addressof(this->succ)); | |
267 (void)tmp; | |
268 } | |
269 else | |
270 { | |
271 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
272 assert(tmp == std::addressof(this->fail)); | |
273 (void)tmp; | |
274 } | |
275 } | |
276 | |
277 template<typename U, typename F> | |
278 result(const result<U, F>& other): is_ok_(other.is_ok()) | |
279 { | |
280 if(other.is_ok()) | |
281 { | |
282 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
283 assert(tmp == std::addressof(this->succ)); | |
284 (void)tmp; | |
285 } | |
286 else | |
287 { | |
288 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
289 assert(tmp == std::addressof(this->fail)); | |
290 (void)tmp; | |
291 } | |
292 } | |
293 template<typename U, typename F> | |
294 result(result<U, F>&& other): is_ok_(other.is_ok()) | |
295 { | |
296 if(other.is_ok()) | |
297 { | |
298 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
299 assert(tmp == std::addressof(this->succ)); | |
300 (void)tmp; | |
301 } | |
302 else | |
303 { | |
304 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
305 assert(tmp == std::addressof(this->fail)); | |
306 (void)tmp; | |
307 } | |
308 } | |
309 | |
310 result& operator=(const result& other) | |
311 { | |
312 this->cleanup(); | |
313 if(other.is_ok()) | |
314 { | |
315 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
316 assert(tmp == std::addressof(this->succ)); | |
317 (void)tmp; | |
318 } | |
319 else | |
320 { | |
321 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
322 assert(tmp == std::addressof(this->fail)); | |
323 (void)tmp; | |
324 } | |
325 is_ok_ = other.is_ok(); | |
326 return *this; | |
327 } | |
328 result& operator=(result&& other) | |
329 { | |
330 this->cleanup(); | |
331 if(other.is_ok()) | |
332 { | |
333 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
334 assert(tmp == std::addressof(this->succ)); | |
335 (void)tmp; | |
336 } | |
337 else | |
338 { | |
339 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
340 assert(tmp == std::addressof(this->fail)); | |
341 (void)tmp; | |
342 } | |
343 is_ok_ = other.is_ok(); | |
344 return *this; | |
345 } | |
346 | |
347 template<typename U, typename F> | |
348 result& operator=(const result<U, F>& other) | |
349 { | |
350 this->cleanup(); | |
351 if(other.is_ok()) | |
352 { | |
353 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
354 assert(tmp == std::addressof(this->succ)); | |
355 (void)tmp; | |
356 } | |
357 else | |
358 { | |
359 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
360 assert(tmp == std::addressof(this->fail)); | |
361 (void)tmp; | |
362 } | |
363 is_ok_ = other.is_ok(); | |
364 return *this; | |
365 } | |
366 template<typename U, typename F> | |
367 result& operator=(result<U, F>&& other) | |
368 { | |
369 this->cleanup(); | |
370 if(other.is_ok()) | |
371 { | |
372 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
373 assert(tmp == std::addressof(this->succ)); | |
374 (void)tmp; | |
375 } | |
376 else | |
377 { | |
378 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
379 assert(tmp == std::addressof(this->fail)); | |
380 (void)tmp; | |
381 } | |
382 is_ok_ = other.is_ok(); | |
383 return *this; | |
384 } | |
385 | |
386 bool is_ok() const noexcept {return is_ok_;} | |
387 bool is_err() const noexcept {return !is_ok_;} | |
388 | |
389 operator bool() const noexcept {return is_ok_;} | |
390 | |
391 value_type& unwrap() & | |
392 { | |
393 if(is_err()) | |
394 { | |
395 throw std::runtime_error("toml::result: bad unwrap: " + | |
396 format_error(this->as_err())); | |
397 } | |
398 return this->succ.value; | |
399 } | |
400 value_type const& unwrap() const& | |
401 { | |
402 if(is_err()) | |
403 { | |
404 throw std::runtime_error("toml::result: bad unwrap: " + | |
405 format_error(this->as_err())); | |
406 } | |
407 return this->succ.value; | |
408 } | |
409 value_type&& unwrap() && | |
410 { | |
411 if(is_err()) | |
412 { | |
413 throw std::runtime_error("toml::result: bad unwrap: " + | |
414 format_error(this->as_err())); | |
415 } | |
416 return std::move(this->succ.value); | |
417 } | |
418 | |
419 value_type& unwrap_or(value_type& opt) & | |
420 { | |
421 if(is_err()) {return opt;} | |
422 return this->succ.value; | |
423 } | |
424 value_type const& unwrap_or(value_type const& opt) const& | |
425 { | |
426 if(is_err()) {return opt;} | |
427 return this->succ.value; | |
428 } | |
429 value_type unwrap_or(value_type opt) && | |
430 { | |
431 if(is_err()) {return opt;} | |
432 return this->succ.value; | |
433 } | |
434 | |
435 error_type& unwrap_err() & | |
436 { | |
437 if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} | |
438 return this->fail.value; | |
439 } | |
440 error_type const& unwrap_err() const& | |
441 { | |
442 if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} | |
443 return this->fail.value; | |
444 } | |
445 error_type&& unwrap_err() && | |
446 { | |
447 if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} | |
448 return std::move(this->fail.value); | |
449 } | |
450 | |
451 value_type& as_ok() & noexcept {return this->succ.value;} | |
452 value_type const& as_ok() const& noexcept {return this->succ.value;} | |
453 value_type&& as_ok() && noexcept {return std::move(this->succ.value);} | |
454 | |
455 error_type& as_err() & noexcept {return this->fail.value;} | |
456 error_type const& as_err() const& noexcept {return this->fail.value;} | |
457 error_type&& as_err() && noexcept {return std::move(this->fail.value);} | |
458 | |
459 | |
460 // prerequisities | |
461 // F: T -> U | |
462 // retval: result<U, E> | |
463 template<typename F> | |
464 result<detail::return_type_of_t<F, value_type&>, error_type> | |
465 map(F&& f) & | |
466 { | |
467 if(this->is_ok()){return ok(f(this->as_ok()));} | |
468 return err(this->as_err()); | |
469 } | |
470 template<typename F> | |
471 result<detail::return_type_of_t<F, value_type const&>, error_type> | |
472 map(F&& f) const& | |
473 { | |
474 if(this->is_ok()){return ok(f(this->as_ok()));} | |
475 return err(this->as_err()); | |
476 } | |
477 template<typename F> | |
478 result<detail::return_type_of_t<F, value_type &&>, error_type> | |
479 map(F&& f) && | |
480 { | |
481 if(this->is_ok()){return ok(f(std::move(this->as_ok())));} | |
482 return err(std::move(this->as_err())); | |
483 } | |
484 | |
485 // prerequisities | |
486 // F: E -> F | |
487 // retval: result<T, F> | |
488 template<typename F> | |
489 result<value_type, detail::return_type_of_t<F, error_type&>> | |
490 map_err(F&& f) & | |
491 { | |
492 if(this->is_err()){return err(f(this->as_err()));} | |
493 return ok(this->as_ok()); | |
494 } | |
495 template<typename F> | |
496 result<value_type, detail::return_type_of_t<F, error_type const&>> | |
497 map_err(F&& f) const& | |
498 { | |
499 if(this->is_err()){return err(f(this->as_err()));} | |
500 return ok(this->as_ok()); | |
501 } | |
502 template<typename F> | |
503 result<value_type, detail::return_type_of_t<F, error_type&&>> | |
504 map_err(F&& f) && | |
505 { | |
506 if(this->is_err()){return err(f(std::move(this->as_err())));} | |
507 return ok(std::move(this->as_ok())); | |
508 } | |
509 | |
510 // prerequisities | |
511 // F: T -> U | |
512 // retval: U | |
513 template<typename F, typename U> | |
514 detail::return_type_of_t<F, value_type&> | |
515 map_or_else(F&& f, U&& opt) & | |
516 { | |
517 if(this->is_err()){return std::forward<U>(opt);} | |
518 return f(this->as_ok()); | |
519 } | |
520 template<typename F, typename U> | |
521 detail::return_type_of_t<F, value_type const&> | |
522 map_or_else(F&& f, U&& opt) const& | |
523 { | |
524 if(this->is_err()){return std::forward<U>(opt);} | |
525 return f(this->as_ok()); | |
526 } | |
527 template<typename F, typename U> | |
528 detail::return_type_of_t<F, value_type&&> | |
529 map_or_else(F&& f, U&& opt) && | |
530 { | |
531 if(this->is_err()){return std::forward<U>(opt);} | |
532 return f(std::move(this->as_ok())); | |
533 } | |
534 | |
535 // prerequisities | |
536 // F: E -> U | |
537 // retval: U | |
538 template<typename F, typename U> | |
539 detail::return_type_of_t<F, error_type&> | |
540 map_err_or_else(F&& f, U&& opt) & | |
541 { | |
542 if(this->is_ok()){return std::forward<U>(opt);} | |
543 return f(this->as_err()); | |
544 } | |
545 template<typename F, typename U> | |
546 detail::return_type_of_t<F, error_type const&> | |
547 map_err_or_else(F&& f, U&& opt) const& | |
548 { | |
549 if(this->is_ok()){return std::forward<U>(opt);} | |
550 return f(this->as_err()); | |
551 } | |
552 template<typename F, typename U> | |
553 detail::return_type_of_t<F, error_type&&> | |
554 map_err_or_else(F&& f, U&& opt) && | |
555 { | |
556 if(this->is_ok()){return std::forward<U>(opt);} | |
557 return f(std::move(this->as_err())); | |
558 } | |
559 | |
560 // prerequisities: | |
561 // F: func T -> U | |
562 // toml::err(error_type) should be convertible to U. | |
563 // normally, type U is another result<S, F> and E is convertible to F | |
564 template<typename F> | |
565 detail::return_type_of_t<F, value_type&> | |
566 and_then(F&& f) & | |
567 { | |
568 if(this->is_ok()){return f(this->as_ok());} | |
569 return err(this->as_err()); | |
570 } | |
571 template<typename F> | |
572 detail::return_type_of_t<F, value_type const&> | |
573 and_then(F&& f) const& | |
574 { | |
575 if(this->is_ok()){return f(this->as_ok());} | |
576 return err(this->as_err()); | |
577 } | |
578 template<typename F> | |
579 detail::return_type_of_t<F, value_type&&> | |
580 and_then(F&& f) && | |
581 { | |
582 if(this->is_ok()){return f(std::move(this->as_ok()));} | |
583 return err(std::move(this->as_err())); | |
584 } | |
585 | |
586 // prerequisities: | |
587 // F: func E -> U | |
588 // toml::ok(value_type) should be convertible to U. | |
589 // normally, type U is another result<S, F> and T is convertible to S | |
590 template<typename F> | |
591 detail::return_type_of_t<F, error_type&> | |
592 or_else(F&& f) & | |
593 { | |
594 if(this->is_err()){return f(this->as_err());} | |
595 return ok(this->as_ok()); | |
596 } | |
597 template<typename F> | |
598 detail::return_type_of_t<F, error_type const&> | |
599 or_else(F&& f) const& | |
600 { | |
601 if(this->is_err()){return f(this->as_err());} | |
602 return ok(this->as_ok()); | |
603 } | |
604 template<typename F> | |
605 detail::return_type_of_t<F, error_type&&> | |
606 or_else(F&& f) && | |
607 { | |
608 if(this->is_err()){return f(std::move(this->as_err()));} | |
609 return ok(std::move(this->as_ok())); | |
610 } | |
611 | |
612 // if *this is error, returns *this. otherwise, returns other. | |
613 result and_other(const result& other) const& | |
614 { | |
615 return this->is_err() ? *this : other; | |
616 } | |
617 result and_other(result&& other) && | |
618 { | |
619 return this->is_err() ? std::move(*this) : std::move(other); | |
620 } | |
621 | |
622 // if *this is okay, returns *this. otherwise, returns other. | |
623 result or_other(const result& other) const& | |
624 { | |
625 return this->is_ok() ? *this : other; | |
626 } | |
627 result or_other(result&& other) && | |
628 { | |
629 return this->is_ok() ? std::move(*this) : std::move(other); | |
630 } | |
631 | |
632 void swap(result<T, E>& other) | |
633 { | |
634 result<T, E> tmp(std::move(*this)); | |
635 *this = std::move(other); | |
636 other = std::move(tmp); | |
637 return ; | |
638 } | |
639 | |
640 private: | |
641 | |
642 static std::string format_error(std::exception const& excpt) | |
643 { | |
644 return std::string(excpt.what()); | |
645 } | |
646 template<typename U, typename std::enable_if<!std::is_base_of< | |
647 std::exception, U>::value, std::nullptr_t>::type = nullptr> | |
648 static std::string format_error(U const& others) | |
649 { | |
650 std::ostringstream oss; oss << others; | |
651 return oss.str(); | |
652 } | |
653 | |
654 void cleanup() noexcept | |
655 { | |
656 if(this->is_ok_) {this->succ.~success_type();} | |
657 else {this->fail.~failure_type();} | |
658 return; | |
659 } | |
660 | |
661 private: | |
662 | |
663 bool is_ok_; | |
664 union | |
665 { | |
666 success_type succ; | |
667 failure_type fail; | |
668 }; | |
669 }; | |
670 | |
671 template<typename T, typename E> | |
672 void swap(result<T, E>& lhs, result<T, E>& rhs) | |
673 { | |
674 lhs.swap(rhs); | |
675 return; | |
676 } | |
677 | |
678 // this might be confusing because it eagerly evaluated, while in the other | |
679 // cases operator && and || are short-circuited. | |
680 // | |
681 // template<typename T, typename E> | |
682 // inline result<T, E> | |
683 // operator&&(const result<T, E>& lhs, const result<T, E>& rhs) noexcept | |
684 // { | |
685 // return lhs.is_ok() ? rhs : lhs; | |
686 // } | |
687 // | |
688 // template<typename T, typename E> | |
689 // inline result<T, E> | |
690 // operator||(const result<T, E>& lhs, const result<T, E>& rhs) noexcept | |
691 // { | |
692 // return lhs.is_ok() ? lhs : rhs; | |
693 // } | |
694 | |
695 // ---------------------------------------------------------------------------- | |
696 // re-use result<T, E> as a optional<T> with none_t | |
697 | |
698 namespace detail | |
699 { | |
700 struct none_t {}; | |
701 inline bool operator==(const none_t&, const none_t&) noexcept {return true;} | |
702 inline bool operator!=(const none_t&, const none_t&) noexcept {return false;} | |
703 inline bool operator< (const none_t&, const none_t&) noexcept {return false;} | |
704 inline bool operator<=(const none_t&, const none_t&) noexcept {return true;} | |
705 inline bool operator> (const none_t&, const none_t&) noexcept {return false;} | |
706 inline bool operator>=(const none_t&, const none_t&) noexcept {return true;} | |
707 template<typename charT, typename traitsT> | |
708 std::basic_ostream<charT, traitsT>& | |
709 operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&) | |
710 { | |
711 os << "none"; | |
712 return os; | |
713 } | |
714 inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};} | |
715 } // detail | |
716 } // toml11 | |
717 #endif// TOML11_RESULT_H |