Embedded Template Library 1.0
Loading...
Searching...
No Matches
expected.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2022 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_EXPECTED_INCLUDED
32#define ETL_EXPECTED_INCLUDED
33
36#include "platform.h"
37#include "error_handler.h"
38#include "exception.h"
39#include "initializer_list.h"
40#include "invoke.h"
41#include "memory.h"
42#include "type_traits.h"
43#include "utility.h"
44#include "variant.h"
45
46namespace etl
47{
48 // Forward declaration for is_expected
49 template <typename TValue, typename TError>
50 class expected;
51
52 template <typename T>
54 {
55 };
56
57 template <typename TValue, typename TError>
58 struct is_expected<expected<TValue, TError> > : etl::true_type
59 {
60 };
61
62 //***************************************************************************
64 //***************************************************************************
65 class expected_exception : public etl::exception
66 {
67 public:
68
69 expected_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
70 : exception(reason_, file_name_, line_number_)
71 {
72 }
73 };
74
75 //***************************************************************************
77 //***************************************************************************
78 class expected_invalid : public etl::expected_exception
79 {
80 public:
81
82 expected_invalid(string_type file_name_, numeric_type line_number_)
83 : expected_exception(ETL_ERROR_TEXT("expected:invalid", ETL_EXPECTED_FILE_ID"A"), file_name_, line_number_)
84 {
85 }
86 };
87
88 //***************************************************************************
91 //***************************************************************************
92 template <typename TError>
94 {
95 public:
96
97 typedef TError error_type;
98
99 //*******************************************
101 //*******************************************
102 ETL_CONSTEXPR unexpected(const unexpected& other)
103 : error_value(other.error_value)
104 {
105 }
106
107#if ETL_USING_CPP11
108 //*******************************************
110 //*******************************************
111 ETL_CONSTEXPR unexpected(unexpected&& other)
112 : error_value(etl::move(other.error_value))
113 {
114 }
115#endif
116
117 //*******************************************
119 //*******************************************
120 ETL_CONSTEXPR explicit unexpected(const TError& e)
121 : error_value(e)
122 {
123 }
124
125#if ETL_USING_CPP11
126 //*******************************************
128 //*******************************************
129 ETL_CONSTEXPR explicit unexpected(TError&& e)
130 : error_value(etl::forward<TError>(e))
131 {
132 }
133
134 //*******************************************
136 //*******************************************
137 template <typename... Args >
138 ETL_CONSTEXPR explicit unexpected(etl::in_place_t, Args&&... args)
139 : error_value(etl::forward<Args>(args)...)
140 {
141 }
142#endif
143
144#if ETL_HAS_INITIALIZER_LIST
145 //*******************************************
147 //*******************************************
148 template <typename U, typename... Args>
149 ETL_CONSTEXPR explicit unexpected(etl::in_place_t, std::initializer_list<U> init, Args&&... args)
150 : error_value(init, etl::forward<Args>(args)...)
151 {
152 }
153#endif
154
155 //*******************************************
157 //*******************************************
159 {
160#if ETL_USING_CPP11
161 ETL_STATIC_ASSERT(etl::is_copy_constructible<TError>::value, "Error not copy assignable");
162#endif
163
164 error_value = rhs.error_value;
165 return *this;
166 }
167
168#if ETL_USING_CPP11
169 //*******************************************
171 //*******************************************
173 {
174 ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::value, "Error not move assignable");
175
176 error_value = etl::move(rhs.error_value);
177 return *this;
178 }
179#endif
180
181#if ETL_USING_CPP11
182 //*******************************************
184 //*******************************************
185 ETL_CONSTEXPR14 TError& error() & ETL_NOEXCEPT
186 {
187 return error_value;
188 }
189
190 //*******************************************
192 //*******************************************
193 ETL_CONSTEXPR14 const TError& error() const& ETL_NOEXCEPT
194 {
195 return error_value;
196 }
197
198 //*******************************************
200 //*******************************************
201 ETL_CONSTEXPR14 TError&& error() && ETL_NOEXCEPT
202 {
203 return etl::move(error_value);
204 }
205
206 //*******************************************
208 //*******************************************
209 ETL_CONSTEXPR14 TError&& error() const&& ETL_NOEXCEPT
210 {
211 return etl::move(error_value);
212 }
213#else
214 //*******************************************
216 //*******************************************
217 const TError& error() const
218 {
219 return error_value;
220 }
221#endif
222
223 //*******************************************
225 //*******************************************
227 {
228 using ETL_OR_STD::swap;
229
230 swap(error_value, other.error_value);
231 }
232
233 private:
234
235 TError error_value;
236 };
237
238 //*****************************************************************************
240 //*****************************************************************************
241 struct unexpect_t
242 {
243 ETL_CONSTEXPR14 explicit unexpect_t() {}
244 };
245
246#if ETL_USING_CPP17
247 inline ETL_CONSTEXPR unexpect_t unexpect{};
248#else
249 static const unexpect_t unexpect;
250#endif
251
252 //*****************************************************************************
254 //*****************************************************************************
255 template <typename TValue, typename TError>
257 {
258 public:
259
260 typedef etl::expected<TValue, TError> this_type;
261 typedef TValue value_type;
262 typedef TError error_type;
263 typedef etl::unexpected<TError> unexpected_type;
264
265#if ETL_USING_CPP11
266 template <typename U>
267 using rebind = expected<U, TError>;
268#endif
269
270 //*******************************************
272 //*******************************************
273 ETL_CONSTEXPR14 expected() ETL_NOEXCEPT
274 : storage(etl::in_place_index_t<Value_Type>(), value_type())
275 {
276 }
277
278 //*******************************************
280 //*******************************************
281 ETL_CONSTEXPR14 expected(const value_type& value_) ETL_NOEXCEPT
282 : storage(etl::in_place_index_t<Value_Type>(), value_)
283 {
284 }
285
286#if ETL_USING_CPP11
287 //*******************************************
289 //*******************************************
290 ETL_CONSTEXPR14 expected(value_type&& value_) ETL_NOEXCEPT
291 : storage(etl::in_place_index_t<Value_Type>(), etl::move(value_))
292 {
293 }
294#endif
295
296 //*******************************************
298 //*******************************************
299 ETL_CONSTEXPR14 expected(const expected& other) ETL_NOEXCEPT
300 : storage(other.storage)
301 {
302 }
303
304#if ETL_USING_CPP11
305 //*******************************************
307 //*******************************************
308 ETL_CONSTEXPR14 expected(expected&& other) ETL_NOEXCEPT
309 : storage(etl::move(other.storage))
310 {
311 }
312#endif
313
314#if ETL_USING_CPP11
315 //*******************************************
317 //*******************************************
318 template <typename G, typename etl::enable_if< !etl::is_convertible<const G&, TError>::value, bool>::type = false>
319 ETL_CONSTEXPR14 explicit expected(const etl::unexpected<G>& ue)
320 : storage(etl::in_place_index_t<Error_Type>(), ue.error())
321 {
322 }
323
324 template <typename G, typename etl::enable_if< etl::is_convertible<const G&, TError>::value, bool>::type = false>
325 ETL_CONSTEXPR14 expected(const etl::unexpected<G>& ue)
326 : storage(etl::in_place_index_t<Error_Type>(), ue.error())
327 {
328 }
329#else
330 template <typename G>
331 explicit expected(const etl::unexpected<G>& ue)
332 : storage(etl::in_place_index_t<Error_Type>(), ue.error())
333 {
334 }
335#endif
336
337#if ETL_USING_CPP11
338 //*******************************************
340 //*******************************************
341 template <typename G, typename etl::enable_if< !etl::is_convertible<const G&, TError>::value, bool>::type = false>
342 ETL_CONSTEXPR14 explicit expected(etl::unexpected<G>&& ue)
343 : storage(etl::in_place_index_t<Error_Type>(), etl::move(ue.error()))
344 {
345 }
346
347 template <typename G, typename etl::enable_if< etl::is_convertible<const G&, TError>::value, bool>::type = false>
348 ETL_CONSTEXPR14 expected(etl::unexpected<G>&& ue)
349 : storage(etl::in_place_index_t<Error_Type>(), etl::move(ue.error()))
350 {
351 }
352#endif
353
354 //*******************************************
356 //*******************************************
357 ETL_CONSTEXPR14 explicit expected(etl::in_place_t) ETL_NOEXCEPT
358 : storage(value_type())
359 {
360 }
361
362#if ETL_USING_CPP11
363 //*******************************************
365 //*******************************************
366 template <typename... Args>
367 ETL_CONSTEXPR14 explicit expected(etl::in_place_t, Args&&... args)
368 : storage(etl::in_place_index_t<Value_Type>(), etl::forward<Args>(args)...)
369 {
370 }
371
372 #if ETL_HAS_INITIALIZER_LIST
373 //*******************************************
375 //*******************************************
376 template <typename U, typename... Args>
377 ETL_CONSTEXPR14 explicit expected(etl::in_place_t, std::initializer_list<U> il, Args&&... args)
378 : storage(etl::in_place_index_t<Value_Type>(), il, etl::forward<Args>(args)...)
379 {
380 }
381 #endif
382
383 //*******************************************
385 //*******************************************
386 template <typename... Args>
387 ETL_CONSTEXPR14 explicit expected(etl::unexpect_t, Args&&... args)
388 : storage(error_type(etl::forward<Args>(args)...))
389 {
390 }
391
392 #if ETL_HAS_INITIALIZER_LIST
393 //*******************************************
395 //*******************************************
396 template <typename U, typename... Args>
397 ETL_CONSTEXPR14 explicit expected(etl::unexpect_t, std::initializer_list<U> il, Args&&... args)
398 : storage(error_type(il, etl::forward<Args>(args)...))
399 {
400 }
401 #endif
402#endif
403
404 //*******************************************
406 //*******************************************
407 this_type& operator=(const this_type& other)
408 {
409 ETL_STATIC_ASSERT(etl::is_copy_constructible<TValue>::value && etl::is_copy_constructible<TError>::value, "Not copy assignable");
410
411 storage = other.storage;
412
413 return *this;
414 }
415
416#if ETL_USING_CPP11
417 //*******************************************
419 //*******************************************
420 this_type& operator=(this_type&& other)
421 {
422 ETL_STATIC_ASSERT(etl::is_move_constructible<TValue>::value && etl::is_move_constructible<TError>::value, "Not move assignable");
423
424 storage = etl::move(other.storage);
425
426 return *this;
427 }
428#endif
429
430 //*******************************************
432 //*******************************************
433 expected& operator=(const value_type& value)
434 {
435 ETL_STATIC_ASSERT(etl::is_copy_constructible<TValue>::value, "Value not copy assignable");
436
437 storage.template emplace<Value_Type>(value);
438
439 return *this;
440 }
441
442#if ETL_USING_CPP11
443 //*******************************************
445 //*******************************************
447 {
448 ETL_STATIC_ASSERT(etl::is_move_constructible<TValue>::value, "Value not move assignable");
449
450 storage.template emplace<Value_Type>(etl::move(value));
451
452 return *this;
453 }
454#endif
455
456 //*******************************************
458 //*******************************************
459 expected& operator=(const unexpected_type& ue)
460 {
461#if ETL_USING_CPP11
462 ETL_STATIC_ASSERT(etl::is_copy_constructible<TError>::value, "Error not copy assignable");
463#endif
464
465 storage.template emplace<Error_Type>(ue.error());
466
467 return *this;
468 }
469
470#if ETL_USING_CPP11
471 //*******************************************
473 //*******************************************
474 expected& operator=(unexpected_type&& ue)
475 {
476 ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::value, "Error not move assignable");
477
478 storage.template emplace<Error_Type>(etl::move(ue.error()));
479
480 return *this;
481 }
482#endif
483
484#if ETL_USING_CPP11
485 //*******************************************
487 //*******************************************
488 ETL_CONSTEXPR14 value_type& value() &
489 {
490 return etl::get<Value_Type>(storage);
491 }
492
493 //*******************************************
495 //*******************************************
496 ETL_CONSTEXPR14 const value_type& value() const&
497 {
498 return etl::get<Value_Type>(storage);
499 }
500
501 //*******************************************
503 //*******************************************
504 ETL_CONSTEXPR14 value_type&& value() &&
505 {
506 return etl::move(etl::get<Value_Type>(storage));
507 }
508
509 //*******************************************
511 //*******************************************
512 ETL_CONSTEXPR14 const value_type&& value() const&&
513 {
514 return etl::move(etl::get<Value_Type>(storage));
515 }
516#else
517 //*******************************************
519 //*******************************************
520 const value_type& value() const
521 {
522 return etl::get<Value_Type>(storage);
523 }
524#endif
525
526 //*******************************************
528 //*******************************************
529 ETL_NODISCARD ETL_CONSTEXPR14 bool has_value() const ETL_NOEXCEPT
530 {
531 return (storage.index() == Value_Type);
532 }
533
534 //*******************************************
536 //*******************************************
537 ETL_NODISCARD ETL_CONSTEXPR14 ETL_EXPLICIT operator bool() const ETL_NOEXCEPT
538 {
539 return has_value();
540 }
541
542#if ETL_USING_CPP11
543 //*******************************************
545 //*******************************************
546 template <typename U>
547 ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t<etl::is_convertible<U, value_type>::value, value_type> value_or(U&& default_value) const&
548 {
549 if (has_value())
550 {
551 return value();
552 }
553 else
554 {
555 return static_cast<value_type>(etl::forward<U>(default_value));
556 }
557 }
558
559 //*******************************************
561 //*******************************************
562 template <typename U>
563 ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t<etl::is_convertible<U, value_type>::value, value_type> value_or(U&& default_value) &&
564 {
565 if (has_value())
566 {
567 return etl::move(value());
568 }
569 else
570 {
571 return static_cast<value_type>(etl::forward<U>(default_value));
572 }
573 }
574
575 //*******************************************
577 //*******************************************
578 ETL_NODISCARD ETL_CONSTEXPR14 error_type& error() & ETL_NOEXCEPT
579 {
580 return etl::get<Error_Type>(storage);
581 }
582
583 //*******************************************
585 //*******************************************
586 ETL_NODISCARD ETL_CONSTEXPR14 const error_type& error() const& ETL_NOEXCEPT
587 {
588 return etl::get<Error_Type>(storage);
589 }
590
591 //*******************************************
593 //*******************************************
594 ETL_NODISCARD ETL_CONSTEXPR14 error_type&& error() && ETL_NOEXCEPT
595 {
596 return etl::move(etl::get<Error_Type>(storage));
597 }
598
599 //*******************************************
601 //*******************************************
602 ETL_NODISCARD ETL_CONSTEXPR14 const error_type&& error() const&& ETL_NOEXCEPT
603 {
604 return etl::move(etl::get<Error_Type>(storage));
605 }
606
607 //*******************************************
609 //*******************************************
610 void swap(this_type& other)
611 {
612 using ETL_OR_STD::swap;
613
614 swap(storage, other.storage);
615 }
616
617 //*******************************************
619 //*******************************************
620 template <typename... Args>
621 ETL_CONSTEXPR14 value_type& emplace(Args&&... args) ETL_NOEXCEPT
622 {
623 storage.template emplace<value_type>(etl::forward<Args>(args)...);
624
625 return value();
626 }
627
628 //*******************************************
630 //*******************************************
631 #if ETL_HAS_INITIALIZER_LIST
632 template <typename U, typename... Args>
633 ETL_CONSTEXPR14 value_type& emplace(std::initializer_list<U> il, Args&&... args) ETL_NOEXCEPT
634 {
635 storage.template emplace<value_type>(il, etl::forward<Args>(args)...);
636
637 return value();
638 }
639 #endif
640#else
641 //*******************************************
643 //*******************************************
644 template <typename U>
645 value_type value_or(const U& default_value) const
646 {
647 if (has_value())
648 {
649 return value();
650 }
651 else
652 {
653 return default_value;
654 }
655 }
656
657 //*******************************************
659 //*******************************************
660 const error_type& error() const
661 {
662 return etl::get<Error_Type>(storage);
663 }
664#endif
665
666 //*******************************************
668 //*******************************************
669 value_type* operator->()
670 {
671 ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR);
672
673 return etl::addressof(etl::get<value_type>(storage));
674 }
675
676 //*******************************************
678 //*******************************************
679 const value_type* operator->() const
680 {
681 ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR);
682
683 return etl::addressof(etl::get<value_type>(storage));
684 }
685
686 //*******************************************
688 //*******************************************
689 value_type& operator*() ETL_LVALUE_REF_QUALIFIER
690 {
691 ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
692
693 return etl::get<value_type>(storage);
694 }
695
696 //*******************************************
698 //*******************************************
699 const value_type& operator*() const ETL_LVALUE_REF_QUALIFIER
700 {
701 ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR);
702
703 return etl::get<value_type>(storage);
704 }
705
706#if ETL_USING_CPP11
707 //*******************************************
709 //*******************************************
710 value_type&& operator*() &&
711 {
712 ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR);
713
714 return etl::move(etl::get<value_type>(storage));
715 }
716
717 //*******************************************
719 //*******************************************
720 const value_type&& operator*() const&&
721 {
722 ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
723
724 return etl::move(etl::get<value_type>(storage));
725 }
726#endif
727
728#if ETL_USING_CPP11
729 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&>::type>::type>
730 auto transform(F&& f) & -> expected<U, TError>
731 {
732 return transform_impl<F, this_type&, U, TValue&>(etl::forward<F>(f), *this);
733 }
734
735 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&>::type>::type>
736 auto transform(F&& f) const& -> expected<U, TError>
737 {
738 return transform_impl<F, const this_type&, U, const TValue&>(etl::forward<F>(f), *this);
739 }
740
741 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&&>::type>::type>
742 auto transform(F&& f) && -> expected<U, TError>
743 {
744 return transform_impl<F, this_type&&, U, TValue&&>(etl::forward<F>(f), etl::move(*this));
745 }
746
747 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&&>::type>::type>
748 auto transform(F&& f) const&& -> expected<U, TError>
749 {
750 return transform_impl<F, const this_type&&, U, const TValue&&>(etl::forward<F>(f), etl::move(*this));
751 }
752
753 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&>::type>::type>
754 auto and_then(F&& f) & -> U
755 {
756 return and_then_impl<F, this_type&, U, TValue&>(etl::forward<F>(f), *this);
757 }
758
759 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&>::type>::type>
760 auto and_then(F&& f) const& -> U
761 {
762 return and_then_impl<F, const this_type&, U, const TValue&>(etl::forward<F>(f), *this);
763 }
764
765 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&&>::type>::type>
766 auto and_then(F&& f) && -> U
767 {
768 return and_then_impl<F, this_type&&, U, TValue&&>(etl::forward<F>(f), etl::move(*this));
769 }
770
771 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&&>::type>::type>
772 auto and_then(F&& f) const&& -> U
773 {
774 return and_then_impl<F, const this_type&&, U, const TValue&&>(etl::forward<F>(f), etl::move(*this));
775 }
776
777 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
778 auto or_else(F&& f) & -> U
779 {
780 return or_else_impl<F, this_type&, U, TError&>(etl::forward<F>(f), *this);
781 }
782
783 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
784 auto or_else(F&& f) const& -> U
785 {
786 return or_else_impl<F, const this_type&, U, const TError&>(etl::forward<F>(f), *this);
787 }
788
789 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
790 auto or_else(F&& f) && -> U
791 {
792 return or_else_impl<F, this_type&&, U, TError&&>(etl::forward<F>(f), etl::move(*this));
793 }
794
795 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
796 auto or_else(F&& f) const&& -> U
797 {
798 return or_else_impl<F, const this_type&&, U, const TError&&>(etl::forward<F>(f), etl::move(*this));
799 }
800
801 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
802 auto transform_error(F&& f) & -> expected<TValue, U>
803 {
804 return transform_error_impl<F, this_type&, U, TError&>(etl::forward<F>(f), *this);
805 }
806
807 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
808 auto transform_error(F&& f) const& -> expected<TValue, U>
809 {
810 return transform_error_impl<F, const this_type&, U, const TError&>(etl::forward<F>(f), *this);
811 }
812
813 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
814 auto transform_error(F&& f) && -> expected<TValue, U>
815 {
816 return transform_error_impl<F, this_type&&, U, TError&&>(etl::forward<F>(f), etl::move(*this));
817 }
818
819 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
820 auto transform_error(F&& f) const&& -> expected<TValue, U>
821 {
822 return transform_error_impl<F, const this_type&&, U, const TError&&>(etl::forward<F>(f), etl::move(*this));
823 }
824#endif
825
826 private:
827
828 enum
829 {
830 Uninitialised,
831 Value_Type,
832 Error_Type
833 };
834
835 typedef etl::variant<etl::monostate, value_type, error_type> storage_type;
836 storage_type storage;
837
838#if ETL_USING_CPP11
839 template < typename F, typename TExp, typename TRet, typename TValueRef, typename = typename etl::enable_if<!etl::is_void<TRet>::value>::type>
840 auto transform_impl(F&& f, TExp&& exp) const -> expected<TRet, TError>
841 {
842 if (exp.has_value())
843 {
844 return expected<TRet, TError>(etl::invoke(etl::forward<F>(f), etl::forward<TValueRef>(etl::get<Value_Type>(exp.storage))));
845 }
846 else
847 {
848 return expected<TRet, TError>(unexpected<TError>(etl::forward<TExp>(exp).error()));
849 }
850 }
851
852 template < typename F, typename TExp, typename TRet, typename TValueRef, typename = typename etl::enable_if<etl::is_void<TRet>::value>::type>
853 auto transform_impl(F&& f, TExp&& exp) const -> expected<void, TError>
854 {
855 if (exp.has_value())
856 {
857 etl::invoke(etl::forward<F>(f), etl::forward<TValueRef>(etl::get<Value_Type>(exp.storage)));
858 return expected<void, TError>();
859 }
860 else
861 {
862 return expected<void, TError>(unexpected<TError>(etl::forward<TExp>(exp).error()));
863 }
864 }
865
866 template < typename F, typename TExp, typename TRet, typename TValueRef,
867 typename = typename etl::enable_if< !etl::is_void<TRet>::value && etl::is_expected<TRet>::value
868 && etl::is_same<typename TRet::error_type, TError>::value>::type>
869 auto and_then_impl(F&& f, TExp&& exp) const -> TRet
870 {
871 if (exp.has_value())
872 {
873 return etl::invoke(etl::forward<F>(f), etl::forward<TValueRef>(etl::get<Value_Type>(exp.storage)));
874 }
875 else
876 {
877 return TRet(unexpected<TError>(etl::forward<TExp>(exp).error()));
878 }
879 }
880
881 template < typename F, typename TExp, typename TRet, typename TErrorRef,
882 typename = typename etl::enable_if< !etl::is_void<TRet>::value && etl::is_expected<TRet>::value
883 && etl::is_same<typename TRet::value_type, TValue>::value>::type>
884 auto or_else_impl(F&& f, TExp&& exp) const -> TRet
885 {
886 if (exp.has_value())
887 {
888 return TRet(etl::forward<TExp>(exp).value());
889 }
890 else
891 {
892 return etl::invoke(etl::forward<F>(f), etl::forward<TErrorRef>(etl::get<Error_Type>(exp.storage)));
893 }
894 }
895
896 template < typename F, typename TExp, typename TRet, typename TErrorRef, typename = typename etl::enable_if<!etl::is_void<TRet>::value>::type>
897 auto transform_error_impl(F&& f, TExp&& exp) const -> expected<TValue, TRet>
898 {
899 if (exp.has_value())
900 {
901 return expected<TValue, TRet>(etl::forward<TExp>(exp).value());
902 }
903 else
904 {
905 return expected<TValue, TRet>(unexpected<TRet>(etl::invoke(etl::forward<F>(f), etl::forward<TErrorRef>(etl::get<Error_Type>(exp.storage)))));
906 }
907 }
908#endif
909 };
910
911 //*****************************************************************************
913 //*****************************************************************************
914 template <typename TError>
915 class expected<void, TError>
916 {
917 public:
918
919 typedef etl::expected<void, TError> this_type;
920 typedef void value_type;
921 typedef TError error_type;
922 typedef etl::unexpected<TError> unexpected_type;
923
924 //*******************************************
926 //*******************************************
927 ETL_CONSTEXPR14 expected()
928 {
929 }
930
931 //*******************************************
933 //*******************************************
934 ETL_CONSTEXPR14 expected(const unexpected_type& ue_)
935 : storage(ue_.error())
936 {
937 }
938
939#if ETL_USING_CPP11
940 //*******************************************
942 //*******************************************
943 ETL_CONSTEXPR14 expected(unexpected_type&& ue_)
944 : storage(etl::move(ue_.error()))
945 {
946 }
947#endif
948
949 //*******************************************
951 //*******************************************
952 ETL_CONSTEXPR14 expected(const this_type& other)
953 : storage(other.storage)
954 {
955 }
956
957#if ETL_USING_CPP11
958 //*******************************************
960 //*******************************************
961 ETL_CONSTEXPR14 expected(this_type&& other)
962 : storage(etl::move(other.storage))
963 {
964 }
965#endif
966
967 //*******************************************
969 //*******************************************
970 this_type& operator=(const this_type& other)
971 {
972 ETL_STATIC_ASSERT(etl::is_copy_constructible<TError>::value, "Not copy assignable");
973
974 storage = other.storage;
975 return *this;
976 }
977
978#if ETL_USING_CPP11
979 //*******************************************
981 //*******************************************
982 this_type& operator=(this_type&& other)
983 {
984 ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::value, "Not move assignable");
985
986 storage = etl::move(other.storage);
987 return *this;
988 }
989#endif
990
991 //*******************************************
993 //*******************************************
994 expected& operator=(const unexpected_type& ue)
995 {
996#if ETL_USING_CPP11
997 ETL_STATIC_ASSERT(etl::is_copy_constructible<TError>::value, "Error not copy assignable");
998#endif
999
1000 storage.template emplace<Error_Type>(ue.error());
1001 return *this;
1002 }
1003
1004#if ETL_USING_CPP11
1005 //*******************************************
1007 //*******************************************
1008 expected& operator=(unexpected_type&& ue)
1009 {
1010 ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::value, "Error not move assignable");
1011
1012 storage.template emplace<Error_Type>(etl::move(ue.error()));
1013 return *this;
1014 }
1015#endif
1016
1017 //*******************************************
1019 //*******************************************
1020 ETL_NODISCARD ETL_CONSTEXPR14 bool has_value() const ETL_NOEXCEPT
1021 {
1022 return (storage.index() != Error_Type);
1023 }
1024
1025 //*******************************************
1027 //*******************************************
1028 ETL_NODISCARD ETL_CONSTEXPR14 ETL_EXPLICIT operator bool() const ETL_NOEXCEPT
1029 {
1030 return has_value();
1031 }
1032
1033#if ETL_USING_CPP11
1034 //*******************************************
1037 //*******************************************
1038 ETL_NODISCARD ETL_CONSTEXPR14 error_type& error() & ETL_NOEXCEPT
1039 {
1040 return etl::get<Error_Type>(storage);
1041 }
1042
1043 //*******************************************
1046 //*******************************************
1047 ETL_NODISCARD ETL_CONSTEXPR14 const error_type& error() const& ETL_NOEXCEPT
1048 {
1049 return etl::get<Error_Type>(storage);
1050 }
1051
1052 //*******************************************
1055 //*******************************************
1056 ETL_NODISCARD ETL_CONSTEXPR14 error_type&& error() && ETL_NOEXCEPT
1057 {
1058 return etl::move(etl::get<Error_Type>(storage));
1059 }
1060
1061 //*******************************************
1064 //*******************************************
1065 ETL_NODISCARD ETL_CONSTEXPR14 const error_type&& error() const&& ETL_NOEXCEPT
1066 {
1067 return etl::move(etl::get<Error_Type>(storage));
1068 }
1069#else
1070 //*******************************************
1073 //*******************************************
1074 const error_type& error() const
1075 {
1076 return etl::get<Error_Type>(storage);
1077 }
1078#endif
1079
1080 //*******************************************
1082 //*******************************************
1083 void swap(this_type& other)
1084 {
1085 using ETL_OR_STD::swap;
1086
1087 swap(storage, other.storage);
1088 }
1089
1090#if ETL_USING_CPP11
1091 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1092 auto transform(F&& f) & -> expected<U, TError>
1093 {
1094 return transform_impl<F, this_type&, U>(etl::forward<F>(f), *this);
1095 }
1096
1097 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1098 auto transform(F&& f) const& -> expected<U, TError>
1099 {
1100 return transform_impl<F, const this_type&, U>(etl::forward<F>(f), *this);
1101 }
1102
1103 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1104 auto transform(F&& f) && -> expected<U, TError>
1105 {
1106 return transform_impl<F, this_type&&, U>(etl::forward<F>(f), etl::move(*this));
1107 }
1108
1109 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1110 auto transform(F&& f) const&& -> expected<U, TError>
1111 {
1112 return transform_impl<F, const this_type&&, U>(etl::forward<F>(f), etl::move(*this));
1113 }
1114
1115 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1116 auto and_then(F&& f) & -> U
1117 {
1118 return and_then_impl<F, this_type&, U>(etl::forward<F>(f), *this);
1119 }
1120
1121 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1122 auto and_then(F&& f) const& -> U
1123 {
1124 return and_then_impl<F, const this_type&, U>(etl::forward<F>(f), *this);
1125 }
1126
1127 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1128 auto and_then(F&& f) && -> U
1129 {
1130 return and_then_impl<F, this_type&&, U>(etl::forward<F>(f), etl::move(*this));
1131 }
1132
1133 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
1134 auto and_then(F&& f) const&& -> U
1135 {
1136 return and_then_impl<F, const this_type&&, U>(etl::forward<F>(f), etl::move(*this));
1137 }
1138
1139 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
1140 auto or_else(F&& f) & -> U
1141 {
1142 return or_else_impl<F, this_type&, U, TError&>(etl::forward<F>(f), *this);
1143 }
1144
1145 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
1146 auto or_else(F&& f) const& -> U
1147 {
1148 return or_else_impl<F, const this_type&, U, const TError&>(etl::forward<F>(f), *this);
1149 }
1150
1151 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
1152 auto or_else(F&& f) && -> U
1153 {
1154 return or_else_impl<F, this_type&&, U, TError&&>(etl::forward<F>(f), etl::move(*this));
1155 }
1156
1157 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
1158 auto or_else(F&& f) const&& -> U
1159 {
1160 return or_else_impl<F, const this_type&&, U, const TError&&>(etl::forward<F>(f), etl::move(*this));
1161 }
1162
1163 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
1164 auto transform_error(F&& f) & -> expected<void, U>
1165 {
1166 return transform_error_impl<F, this_type&, U, TError&>(etl::forward<F>(f), *this);
1167 }
1168
1169 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
1170 auto transform_error(F&& f) const& -> expected<void, U>
1171 {
1172 return transform_error_impl<F, const this_type&, U, const TError&>(etl::forward<F>(f), *this);
1173 }
1174
1175 template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
1176 auto transform_error(F&& f) && -> expected<void, U>
1177 {
1178 return transform_error_impl<F, this_type&&, U, TError&&>(etl::forward<F>(f), etl::move(*this));
1179 }
1180
1181 template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
1182 auto transform_error(F&& f) const&& -> expected<void, U>
1183 {
1184 return transform_error_impl<F, const this_type&&, U, const TError&&>(etl::forward<F>(f), *this);
1185 }
1186#endif
1187
1188 private:
1189
1190 enum
1191 {
1192 Uninitialised,
1193 Error_Type
1194 };
1195
1196 etl::variant<etl::monostate, error_type> storage;
1197
1198#if ETL_USING_CPP11
1199 template < typename F, typename TExp, typename TRet, typename = typename etl::enable_if<!etl::is_void<TRet>::value>::type>
1200 auto transform_impl(F&& f, TExp&& exp) const -> expected<TRet, TError>
1201 {
1202 if (exp.has_value())
1203 {
1204 return expected<TRet, TError>(etl::invoke(etl::forward<F>(f)));
1205 }
1206 else
1207 {
1208 return expected<TRet, TError>(unexpected<TError>(etl::forward<TExp>(exp).error()));
1209 }
1210 }
1211
1212 template < typename F, typename TExp, typename TRet, typename = typename etl::enable_if<etl::is_void<TRet>::value>::type>
1213 auto transform_impl(F&& f, TExp&& exp) const -> expected<void, TError>
1214 {
1215 if (exp.has_value())
1216 {
1217 etl::invoke(etl::forward<F>(f));
1218 return expected<void, TError>();
1219 }
1220 else
1221 {
1222 return expected<void, TError>(unexpected<TError>(etl::forward<TExp>(exp).error()));
1223 }
1224 }
1225
1226 template < typename F, typename TExp, typename TRet,
1227 typename = typename etl::enable_if< !etl::is_void<TRet>::value && etl::is_expected<TRet>::value
1228 && etl::is_same<typename TRet::error_type, TError>::value>::type>
1229 auto and_then_impl(F&& f, TExp&& exp) const -> TRet
1230 {
1231 if (exp.has_value())
1232 {
1233 return etl::invoke(etl::forward<F>(f));
1234 }
1235 else
1236 {
1237 return TRet(unexpected<TError>(etl::forward<TExp>(exp).error()));
1238 }
1239 }
1240
1241 template <typename F, typename TExp, typename TRet, typename TErrorRef,
1242 typename = typename etl::enable_if< !etl::is_void<TRet>::value && etl::is_expected<TRet>::value
1243 && etl::is_same<typename TRet::value_type, void>::value>::type>
1244 auto or_else_impl(F&& f, TExp&& exp) const -> TRet
1245 {
1246 if (exp.has_value())
1247 {
1248 return TRet();
1249 }
1250 else
1251 {
1252 return etl::invoke(etl::forward<F>(f), etl::forward<TErrorRef>(etl::get<Error_Type>(exp.storage)));
1253 }
1254 }
1255
1256 template < typename F, typename TExp, typename TRet, typename TErrorRef, typename = typename etl::enable_if<!etl::is_void<TRet>::value>::type>
1257 auto transform_error_impl(F&& f, TExp&& exp) const -> expected<void, TRet>
1258 {
1259 if (exp.has_value())
1260 {
1261 return expected<void, TRet>();
1262 }
1263 else
1264 {
1265 return expected<void, TRet>(unexpected<TRet>(etl::invoke(etl::forward<F>(f), etl::forward<TErrorRef>(etl::get<Error_Type>(exp.storage)))));
1266 }
1267 }
1268#endif
1269 };
1270
1271 //*******************************************
1273 //*******************************************
1274 template <typename TValue, typename TError, typename TValue2, typename TError2>
1276 {
1277 if (lhs.has_value() != rhs.has_value())
1278 {
1279 return false;
1280 }
1281 if (lhs.has_value())
1282 {
1283 return lhs.value() == rhs.value();
1284 }
1285 return lhs.error() == rhs.error();
1286 }
1287
1288 //*******************************************
1289 template <typename TValue, typename TError, typename TValue2>
1290 ETL_CONSTEXPR14 bool operator==(const etl::expected<TValue, TError>& lhs, const TValue2& rhs)
1291 {
1292 if (!lhs.has_value())
1293 {
1294 return false;
1295 }
1296 return lhs.value() == rhs;
1297 }
1298
1299 //*******************************************
1300 template <typename TValue, typename TError, typename TError2>
1301 ETL_CONSTEXPR14 bool operator==(const etl::expected<TValue, TError>& lhs, const etl::unexpected<TError2>& rhs)
1302 {
1303 if (lhs.has_value())
1304 {
1305 return false;
1306 }
1307 return lhs.error() == rhs.error();
1308 }
1309
1310 //*******************************************
1311 template <typename TError, typename TError2>
1312 ETL_CONSTEXPR14 bool operator==(const etl::expected<void, TError>& lhs, const etl::expected<void, TError2>& rhs)
1313 {
1314 if (lhs.has_value() != rhs.has_value())
1315 {
1316 return false;
1317 }
1318 if (lhs.has_value())
1319 {
1320 return true;
1321 }
1322 return lhs.error() == rhs.error();
1323 }
1324
1325 //*******************************************
1326 template <typename TError, typename TError2>
1327 ETL_CONSTEXPR14 bool operator==(const etl::expected<void, TError>& lhs, const etl::unexpected<TError2>& rhs)
1328 {
1329 if (lhs.has_value())
1330 {
1331 return false;
1332 }
1333 return lhs.error() == rhs.error();
1334 }
1335
1336 //*******************************************
1337 template <typename TError, typename TError2>
1338 ETL_CONSTEXPR14 bool operator==(const etl::unexpected<TError>& lhs, const etl::unexpected<TError2>& rhs)
1339 {
1340 return lhs.error() == rhs.error();
1341 }
1342
1343 //*******************************************
1344 template <typename TValue, typename TError, typename TValue2, typename TError2>
1345 ETL_CONSTEXPR14 bool operator!=(const etl::expected<TValue, TError>& lhs, const etl::expected<TValue2, TError2>& rhs)
1346 {
1347 return !(lhs == rhs);
1348 }
1349
1350 //*******************************************
1351 template <typename TValue, typename TError, typename TValue2>
1352 ETL_CONSTEXPR14 bool operator!=(const etl::expected<TValue, TError>& lhs, const TValue2& rhs)
1353 {
1354 return !(lhs == rhs);
1355 }
1356
1357 //*******************************************
1358 template <typename TValue, typename TError, typename TError2>
1359 ETL_CONSTEXPR14 bool operator!=(const etl::expected<TValue, TError>& lhs, const etl::unexpected<TError2>& rhs)
1360 {
1361 return !(lhs == rhs);
1362 }
1363
1364 //*******************************************
1365 template <typename TError, typename TError2>
1366 ETL_CONSTEXPR14 bool operator!=(const etl::expected<void, TError>& lhs, const etl::expected<void, TError2>& rhs)
1367 {
1368 return !(lhs == rhs);
1369 }
1370
1371 //*******************************************
1372 template <typename TError, typename TError2>
1373 ETL_CONSTEXPR14 bool operator!=(const etl::expected<void, TError>& lhs, const etl::unexpected<TError2>& rhs)
1374 {
1375 return !(lhs == rhs);
1376 }
1377
1378 //*******************************************
1379 template <typename TError, typename TError2>
1380 ETL_CONSTEXPR14 bool operator!=(const etl::unexpected<TError>& lhs, const etl::unexpected<TError2>& rhs)
1381 {
1382 return !(lhs == rhs);
1383 }
1384} // namespace etl
1385
1386//*******************************************
1388//*******************************************
1389template <typename TValue, typename TError>
1391{
1392 lhs.swap(rhs);
1393}
1394
1395//*******************************************
1397//*******************************************
1398template <typename TError>
1400{
1401 lhs.swap(rhs);
1402}
1403
1404#endif
expected & operator=(const unexpected_type &ue)
Copy assign from unexpected.
Definition expected.h:994
ETL_CONSTEXPR14 expected()
Default constructor.
Definition expected.h:927
ETL_NODISCARD ETL_CONSTEXPR14 bool has_value() const ETL_NOEXCEPT
Returns true if expected has a value.
Definition expected.h:1020
ETL_CONSTEXPR14 expected(const unexpected_type &ue_)
Copy construct from unexpected.
Definition expected.h:934
void swap(this_type &other)
Swap with another etl::expected.
Definition expected.h:1083
ETL_CONSTEXPR14 expected(const this_type &other)
Copy construct.
Definition expected.h:952
const error_type & error() const
Definition expected.h:1074
this_type & operator=(const this_type &other)
Copy assign.
Definition expected.h:970
Base exception for et::expected.
Definition expected.h:66
Expected type.
Definition expected.h:257
ETL_CONSTEXPR14 expected() ETL_NOEXCEPT
Default constructor.
Definition expected.h:273
ETL_CONSTEXPR14 expected(const value_type &value_) ETL_NOEXCEPT
Constructor.
Definition expected.h:281
this_type & operator=(const this_type &other)
Copy assign from etl::expected.
Definition expected.h:407
expected & operator=(const value_type &value)
Copy assign from value.
Definition expected.h:433
ETL_CONSTEXPR14 expected(etl::in_place_t) ETL_NOEXCEPT
Construct with default value type.
Definition expected.h:357
ETL_CONSTEXPR14 expected(const expected &other) ETL_NOEXCEPT
Copy constructor.
Definition expected.h:299
expected & operator=(const unexpected_type &ue)
Copy assign from unexpected.
Definition expected.h:459
const value_type & value() const
Get the value.
Definition expected.h:520
Definition expected.h:94
const TError & error() const
Get the error.
Definition expected.h:217
void swap(etl::unexpected< TError > &other)
Swap with another etl::unexpected.
Definition expected.h:226
ETL_CONSTEXPR unexpected(const unexpected &other)
Copy constructor.
Definition expected.h:102
ETL_CONSTEXPR unexpected(const TError &e)
Construct from an lvalue.
Definition expected.h:120
ETL_CONSTEXPR14 etl::unexpected< TError > & operator=(const etl::unexpected< TError > &rhs)
Assign from etl::unexpected.
Definition expected.h:158
ETL_CONSTEXPR14 void swap(etl::expected< TValue, TError > &lhs, etl::expected< TValue, TError > &rhs)
Swap etl::expected.
Definition expected.h:1390
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
ETL_CONSTEXPR17 etl::enable_if<!etl::is_same< T, etl::nullptr_t >::value, T >::type * addressof(T &t)
Definition addressof.h:52
size_t index() const
Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID.
Definition variant_legacy.h:718
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:856
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
T & get(array< T, Size > &a)
Definition array.h:1161
Definition utility.h:950
in_place disambiguation tags.
Definition utility.h:927
Definition expected.h:54
unexpect_t
Definition expected.h:242