]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentracing-cpp/3rd_party/include/opentracing/expected/expected.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / opentracing-cpp / 3rd_party / include / opentracing / expected / expected.hpp
1 // Copyright (C) 2016 Martin Moene.
2 //
3 // This version targets C++11 and later.
4 //
5 // This code is licensed under the MIT License (MIT).
6 //
7 // expected lite is based on:
8 // A proposal to add a utility class to represent expected monad - Revision 2
9 // by Vicente J. Botet Escriba and Pierre Talbot.
10
11 #ifndef OPENTRACING_EXPECTED_LITE_HPP
12 #define OPENTRACING_EXPECTED_LITE_HPP
13
14 #include <cassert>
15 #include <exception>
16 #include <functional>
17 #include <initializer_list>
18 #include <new>
19 #include <stdexcept>
20 #include <type_traits>
21 #include <utility>
22 #include <opentracing/version.h>
23
24 #define expected_lite_VERSION "0.0.0"
25
26 // Compiler detection:
27
28 #define nsel_CPP11_OR_GREATER ( __cplusplus >= 201103L )
29 #define nsel_CPP14_OR_GREATER ( __cplusplus >= 201402L )
30
31 #if nsel_CPP14_OR_GREATER
32 # define nsel_constexpr14 constexpr
33 #else
34 # define nsel_constexpr14 /*constexpr*/
35 #endif
36
37 // Method enabling
38
39 #define nsel_REQUIRES(...) \
40 typename std::enable_if<__VA_ARGS__, void*>::type = 0
41
42 #define nsel_REQUIRES_0(...) \
43 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
44
45 #define nsel_REQUIRES_T(...) \
46 typename = typename std::enable_if< (__VA_ARGS__), opentracing::expected_detail::enabler >::type
47
48 namespace opentracing {
49 BEGIN_OPENTRACING_ABI_NAMESPACE
50
51 template< typename T, typename E >
52 class expected;
53
54 namespace expected_detail {
55
56 /// for nsel_REQUIRES_T
57
58 enum class enabler{};
59
60 /// discriminated union to hold value or 'error'.
61
62 template< typename T, typename E >
63 union storage_t
64 {
65 friend class expected<T,E>;
66
67 private:
68 typedef T value_type;
69 typedef E error_type;
70
71 // no-op construction
72 storage_t() {}
73 ~storage_t() {}
74
75 void construct_value( value_type const & v )
76 {
77 new( &m_value ) value_type( v );
78 }
79
80 void construct_value( value_type && v )
81 {
82 new( &m_value ) value_type( std::forward<T>( v ) );
83 }
84
85 void destruct_value()
86 {
87 m_value.~value_type();
88 }
89
90 void construct_error( error_type const & e )
91 {
92 new( &m_error ) error_type( e );
93 }
94
95 void construct_error( error_type && e )
96 {
97 new( &m_error ) error_type( std::move( e ) );
98 }
99
100 void destruct_error()
101 {
102 m_error.~error_type();
103 }
104
105 constexpr value_type const & value() const &
106 {
107 return m_value;
108 }
109
110 value_type & value() &
111 {
112 return m_value;
113 }
114
115 constexpr value_type && value() const &&
116 {
117 return std::move( m_value );
118 }
119
120 const value_type * value_ptr() const
121 {
122 return &m_value;
123 }
124
125 value_type * value_ptr()
126 {
127 return &m_value;
128 }
129
130 error_type const & error() const
131 {
132 return m_error;
133 }
134
135 error_type & error()
136 {
137 return m_error;
138 }
139
140 private:
141 value_type m_value;
142 error_type m_error;
143 };
144
145 /// discriminated union to hold only 'error'.
146
147 template< typename E >
148 union storage_t<void, E>
149 {
150 friend class expected<void,E>;
151
152 private:
153 typedef void value_type;
154 typedef E error_type;
155
156 // no-op construction
157 storage_t() {}
158 ~storage_t() {}
159
160 void construct_error( error_type const & e )
161 {
162 new( &m_error ) error_type( e );
163 }
164
165 void construct_error( error_type && e )
166 {
167 new( &m_error ) error_type( std::move( e ) );
168 }
169
170 void destruct_error()
171 {
172 m_error.~error_type();
173 }
174
175 error_type const & error() const
176 {
177 return m_error;
178 }
179
180 error_type & error()
181 {
182 return m_error;
183 }
184
185 private:
186 error_type m_error;
187 };
188
189 } // namespace expected_detail
190
191 /// class unexpected_type
192
193 template< typename E = std::error_code >
194 class unexpected_type
195 {
196 public:
197 typedef E error_type;
198
199 unexpected_type() = delete;
200
201 nsel_REQUIRES_0(
202 std::is_copy_constructible<error_type>::value )
203
204 constexpr explicit unexpected_type( error_type const & error )
205 : m_error( error )
206 {}
207
208 nsel_REQUIRES_0(
209 std::is_move_constructible<error_type>::value )
210
211 constexpr explicit unexpected_type( error_type && error )
212 : m_error( std::move( error ) )
213 {}
214
215 constexpr error_type const & value() const
216 {
217 return m_error;
218 }
219
220 error_type & value()
221 {
222 return m_error;
223 }
224
225 private:
226 error_type m_error;
227 };
228
229 /// class unexpected_type, std::exception_ptr specialization
230
231 template<>
232 class unexpected_type< std::exception_ptr >
233 {
234 public:
235 typedef std::exception_ptr error_type;
236
237 unexpected_type() = delete;
238
239 ~unexpected_type(){}
240
241 explicit unexpected_type( std::exception_ptr const & error )
242 : m_error( error )
243 {}
244
245 explicit unexpected_type(std::exception_ptr && error )
246 : m_error( std::move( error ) )
247 {}
248
249 template< typename E >
250 explicit unexpected_type( E error )
251 : m_error( std::make_exception_ptr( error ) )
252 {}
253
254 std::exception_ptr const & value() const
255 {
256 return m_error;
257 }
258
259 std::exception_ptr & value()
260 {
261 return m_error;
262 }
263
264 private:
265 std::exception_ptr m_error;
266 };
267
268 // unexpected: relational operators
269
270 template< typename E >
271 constexpr bool operator==( unexpected_type<E> const & x, unexpected_type<E> const & y )
272 {
273 return x.value() == y.value();
274 }
275
276 template< typename E >
277 constexpr bool operator!=( unexpected_type<E> const & x, unexpected_type<E> const & y )
278 {
279 return ! ( x == y );
280 }
281
282 template< typename E >
283 constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y )
284 {
285 return x.value() < y.value();
286 }
287
288 template< typename E >
289 constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y )
290 {
291 return ( y < x );
292 }
293
294 template< typename E >
295 constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y )
296 {
297 return ! ( y < x );
298 }
299
300 template< typename E >
301 constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y )
302 {
303 return ! ( x < y );
304 }
305
306 inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
307 {
308 return false;
309 }
310
311 inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
312 {
313 return false;
314 }
315
316 inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
317 {
318 return ( x == y );
319 }
320
321 inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
322 {
323 return ( x == y );
324 }
325
326 // unexpected: traits
327
328 template <typename E>
329 struct is_unexpected : std::false_type {};
330
331 template <typename E>
332 struct is_unexpected< unexpected_type<E> > : std::true_type {};
333
334 // unexpected: factory
335
336 template< typename E>
337 nsel_constexpr14 auto
338 make_unexpected( E && v) -> unexpected_type< typename std::decay<E>::type >
339 {
340 return unexpected_type< typename std::decay<E>::type >( v );
341 }
342
343 /*nsel_constexpr14*/ inline auto
344 make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
345 {
346 return unexpected_type< std::exception_ptr >( std::current_exception() );
347 }
348
349 /// in-place tag: construct a value in-place (should come from std::experimental::optional)
350
351 struct in_place_t{};
352
353 constexpr in_place_t in_place{};
354
355 /// unexpect tag, in_place_unexpected tag: construct an error
356
357 struct in_place_unexpected_t{};
358
359 constexpr in_place_unexpected_t unexpect{};
360 constexpr in_place_unexpected_t in_place_unexpected{};
361
362 /// expected access error
363
364 template< typename E >
365 class bad_expected_access : public std::logic_error
366 {
367 public:
368 typedef E error_type;
369
370 explicit bad_expected_access( error_type error )
371 : logic_error( "bad_expected_access" )
372 , m_error( error )
373 {}
374
375 constexpr error_type const & error() const
376 {
377 return m_error;
378 }
379
380 error_type & error()
381 {
382 return m_error;
383 }
384
385 private:
386 error_type m_error;
387 };
388
389 /// class error_traits
390
391 template< typename Error >
392 struct error_traits
393 {
394 static void rethrow( Error const & e )
395 {
396 throw bad_expected_access<Error>{ e };
397 }
398 };
399
400 template<>
401 struct error_traits< std::exception_ptr >
402 {
403 static void rethrow( std::exception_ptr const & e )
404 {
405 std::rethrow_exception( e );
406 }
407 };
408
409 template<>
410 struct error_traits< std::error_code >
411 {
412 static void rethrow( std::error_code const & e )
413 {
414 throw std::system_error( e );
415 }
416 };
417
418 /// class expected
419
420 template< typename T, typename E = std::error_code >
421 class expected
422 {
423 public:
424 typedef T value_type;
425 typedef E error_type;
426
427 // constructors
428
429 nsel_REQUIRES_0(
430 std::is_default_constructible<T>::value )
431
432 nsel_constexpr14 expected() noexcept
433 (
434 std::is_nothrow_default_constructible<T>::value
435 )
436 : has_value_( true )
437 {
438 contained.construct_value( value_type() );
439 }
440
441 // nsel_REQUIRES_0(
442 // std::is_copy_constructible<T>::value &&
443 // std::is_copy_constructible<E>::value )
444
445 nsel_constexpr14 expected( expected const & rhs )
446 : has_value_( rhs.has_value_ )
447 {
448 if ( has_value() ) contained.construct_value( rhs.contained.value() );
449 else contained.construct_error( rhs.contained.error() );
450 }
451
452 // nsel_REQUIRES_0(
453 // std::is_move_constructible<T>::value &&
454 // std::is_move_constructible<E>::value )
455
456 nsel_constexpr14 expected( expected && rhs )
457 : has_value_( rhs.has_value_ )
458 {
459 if ( has_value() ) contained.construct_value( std::move( rhs.contained.value() ) );
460 else contained.construct_error( std::move( rhs.contained.error() ) );
461 }
462
463 nsel_REQUIRES_0(
464 std::is_copy_constructible<T>::value )
465
466 nsel_constexpr14 expected( value_type const & rhs )
467 : has_value_( true )
468 {
469 contained.construct_value( rhs );
470 }
471
472 nsel_REQUIRES_0(
473 std::is_move_constructible<T>::value )
474
475 nsel_constexpr14 expected( value_type && rhs ) noexcept
476 (
477 std::is_nothrow_move_constructible<T>::value &&
478 std::is_nothrow_move_constructible<E>::value
479 )
480 : has_value_( true )
481 {
482 contained.construct_value( std::move( rhs ) );
483 }
484
485 template <typename... Args, nsel_REQUIRES_T(
486 std::is_constructible<T, Args&&...>::value ) >
487
488 nsel_constexpr14 explicit expected( in_place_t, Args&&... args )
489 : has_value_( true )
490 {
491 contained.construct_value( std::forward<Args>( args )... );
492 }
493
494 template< typename U, typename... Args, nsel_REQUIRES_T(
495 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value ) >
496
497 nsel_constexpr14 explicit expected( in_place_t, std::initializer_list<U> il, Args&&... args )
498 : has_value_( true )
499 {
500 contained.construct_value( il, std::forward<Args>( args )... );
501 }
502
503 nsel_REQUIRES_0(
504 std::is_copy_constructible<E>::value )
505
506 nsel_constexpr14 expected( unexpected_type<E> const & error )
507 : has_value_( false )
508 {
509 contained.construct_error( error.value() );
510 }
511
512 nsel_REQUIRES_0(
513 std::is_move_constructible<E>::value )
514
515 nsel_constexpr14 expected( unexpected_type<E> && error )
516 : has_value_( false )
517 {
518 contained.construct_error( std::move( error.value() ) );
519 }
520
521 template< typename... Args, nsel_REQUIRES_T(
522 std::is_constructible<E, Args&&...>::value ) >
523
524 nsel_constexpr14 explicit expected( in_place_unexpected_t, Args&&... args )
525 : has_value_( false )
526 {
527 contained.construct_error( std::forward<Args>( args )... );
528 }
529
530 template< typename U, typename... Args, nsel_REQUIRES_T(
531 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value ) >
532
533 nsel_constexpr14 explicit expected( in_place_unexpected_t, std::initializer_list<U> il, Args&&... args )
534 : has_value_( false )
535 {
536 contained.construct_error( il, std::forward<Args>( args )... );
537 }
538
539 // destructor
540
541 ~expected()
542 {
543 if ( has_value() ) contained.destruct_value();
544 else contained.destruct_error();
545 }
546
547 // assignment
548
549 // nsel_REQUIRES(
550 // std::is_copy_constructible<T>::value &&
551 // std::is_copy_assignable<T>::value &&
552 // std::is_copy_constructible<E>::value &&
553 // std::is_copy_assignable<E>::value )
554
555 expected operator=( expected const & rhs )
556 {
557 expected( rhs ).swap( *this );
558 return *this;
559 }
560
561 // nsel_REQUIRES(
562 // std::is_move_constructible<T>::value &&
563 // std::is_move_assignable<T>::value &&
564 // std::is_move_constructible<E>::value &&
565 // std::is_move_assignable<E>::value )
566
567 expected & operator=( expected && rhs ) noexcept
568 (
569 std::is_nothrow_move_assignable<T>::value &&
570 std::is_nothrow_move_constructible<T>::value&&
571 std::is_nothrow_move_assignable<E>::value &&
572 std::is_nothrow_move_constructible<E>::value )
573 {
574 expected( std::move( rhs ) ).swap( *this );
575 return *this;
576 }
577
578 template< typename U, nsel_REQUIRES_T(
579 std::is_constructible<T,U>::value &&
580 std::is_assignable<T&, U>::value ) >
581
582 expected & operator=( U && v )
583 {
584 expected( std::forward<U>( v ) ).swap( *this );
585 return *this;
586 }
587
588 // nsel_REQUIRES(
589 // std::is_copy_constructible<E>::value &&
590 // std::is_assignable<E&, E>::value )
591
592 expected & operator=( unexpected_type<E> const & u )
593 {
594 expected( std::move( u ) ).swap( *this );
595 return *this;
596 }
597
598 // nsel_REQUIRES(
599 // std::is_copy_constructible<E>::value &&
600 // std::is_assignable<E&, E>::value )
601
602 expected & operator=( unexpected_type<E> && u )
603 {
604 expected( std::move( u ) ).swap( *this );
605 return *this;
606 }
607
608 template< typename... Args, nsel_REQUIRES_T(
609 std::is_constructible<T, Args&&...>::value ) >
610
611 void emplace( Args &&... args )
612 {
613 expected( in_place, std::forward<Args>(args)... ).swap( *this );
614 }
615
616 template< typename U, typename... Args, nsel_REQUIRES_T(
617 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value ) >
618
619 void emplace( std::initializer_list<U> il, Args &&... args )
620 {
621 expected( in_place, il, std::forward<Args>(args)... ).swap( *this );
622 }
623
624 // nsel_REQUIRES(
625 // std::is_move_constructible<T>::value &&
626 // std::is_move_constructible<E>::value )
627
628 void swap( expected & rhs ) noexcept
629 (
630 std::is_nothrow_move_constructible<T>::value && noexcept( std::swap( std::declval<T&>(), std::declval<T&>() ) ) &&
631 std::is_nothrow_move_constructible<E>::value && noexcept( std::swap( std::declval<E&>(), std::declval<E&>() ) ) )
632 {
633 using std::swap;
634
635 if ( bool(*this) && bool(rhs) ) { swap( contained.value(), rhs.contained.value() ); }
636 else if ( ! bool(*this) && ! bool(rhs) ) { swap( contained.error(), rhs.contained.error() ); }
637 else if ( bool(*this) && ! bool(rhs) ) { error_type t( std::move( rhs.error() ) );
638 // TBD - ?? rhs.contained.destruct_error();
639 rhs.contained.construct_value( std::move( contained.value() ) );
640 // TBD - ?? contained.destruct_value();
641 contained.construct_error( std::move( t ) );
642 swap( has_value_, rhs.has_value_ ); }
643 else if ( ! bool(*this) && bool(rhs) ) { rhs.swap( *this ); }
644 }
645
646 // observers
647
648 constexpr value_type const * operator ->() const
649 {
650 return assert( has_value() ), contained.value_ptr();
651 }
652
653 value_type * operator ->()
654 {
655 return assert( has_value() ), contained.value_ptr();
656 }
657
658 constexpr value_type const & operator *() const &
659 {
660 return assert( has_value() ), contained.value();
661 }
662
663 value_type & operator *() &
664 {
665 return assert( has_value() ), contained.value();
666 }
667
668 constexpr value_type && operator *() const &&
669 {
670 return assert( has_value() ), std::move( contained.value() );
671 }
672
673 value_type && operator *() &&
674 {
675 return assert( has_value() ), std::move( contained.value() );
676 }
677
678
679 constexpr explicit operator bool() const noexcept
680 {
681 return has_value();
682 }
683
684 constexpr bool has_value() const noexcept
685 {
686 return has_value_;
687 }
688
689 constexpr value_type const & value() const &
690 {
691 return has_value()
692 ? ( contained.value() )
693 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
694 }
695
696 value_type & value() &
697 {
698 return has_value()
699 ? ( contained.value() )
700 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
701 }
702
703 value_type && value() &&
704 {
705 return has_value()
706 ? ( contained.value() )
707 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
708 }
709
710 constexpr error_type const & error() const &
711 {
712 return assert( ! has_value() ), contained.error();
713 }
714
715 error_type & error() &
716 {
717 return assert( ! has_value() ), contained.error();
718 }
719
720 constexpr error_type && error() const &&
721 {
722 return assert( ! has_value() ), std::move( contained.error() );
723 }
724
725 constexpr unexpected_type<E> get_unexpected() const
726 {
727 return make_unexpected( contained.error() );
728 }
729
730 template< typename Ex >
731 bool has_exception() const
732 {
733 return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value;
734 }
735
736 template< typename U, nsel_REQUIRES_T(
737 std::is_copy_constructible<T>::value &&
738 std::is_convertible<U&&, T>::value ) >
739
740 value_type value_or( U && v ) const &
741 {
742 return has_value()
743 ? contained.value()
744 : static_cast<T>( std::forward<U>( v ) );
745 }
746
747 template< typename U, nsel_REQUIRES_T(
748 std::is_move_constructible<T>::value &&
749 std::is_convertible<U&&, T>::value ) >
750
751 value_type value_or( U && v ) &&
752 {
753 return has_value()
754 ? std::move( contained.value() )
755 : static_cast<T>( std::forward<U>( v ) );
756 }
757
758 // unwrap()
759
760 // template <class U, class E>
761 // constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
762
763 // template <class T, class E>
764 // constexpr expected<T,E> expected<T,E>::unwrap() const&;
765
766 // template <class U, class E>
767 // expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
768
769 // template <class T, class E>
770 // template expected<T,E> expected<T,E>::unwrap() &&;
771
772 // factories
773
774 // template <typename Ex, typename F>
775 // expected<T,E> catch_exception(F&& f);
776
777 // template <typename F>
778 // expected<decltype(func(declval<T>())),E> map(F&& func) ;
779
780 // template <typename F>
781 // \92see below\92 bind(F&& func);
782
783 // template <typename F>
784 // expected<T,E> catch_error(F&& f);
785
786 // template <typename F>
787 // \92see below\92 then(F&& func);
788
789 private:
790 bool has_value_;
791 expected_detail::storage_t<T,E> contained;
792 };
793
794 /// class expected, void specialization
795
796 template< typename E >
797 class expected<void, E>
798 {
799 public:
800 typedef void value_type;
801 typedef E error_type;
802
803 template< typename U >
804 struct rebind
805 {
806 typedef expected<U, error_type> type;
807 };
808
809 // constructors
810
811 constexpr expected() noexcept
812 : has_value_( true )
813 {
814 }
815
816 // nsel_REQUIRES_0(
817 // std::is_copy_constructible<E>::value )
818
819 nsel_constexpr14 expected( expected const & rhs )
820 : has_value_( rhs.has_value_ )
821 {
822 if ( ! has_value() ) contained.construct_error( rhs.contained.error() );
823 }
824
825 nsel_REQUIRES_0(
826 std::is_move_constructible<E>::value )
827
828 nsel_constexpr14 expected( expected && rhs ) noexcept
829 (
830 true // TBD - see also non-void specialization
831 )
832 : has_value_( rhs.has_value_ )
833 {
834 if ( ! has_value() ) contained.construct_error( std::move( rhs.contained.error() ) );
835 }
836
837 //nsel_REQUIRES_0(
838 // std::is_default_constructible<E>::value )
839
840 constexpr explicit expected( in_place_t )
841 : has_value_( true )
842 {
843 }
844
845 // nsel_REQUIRES(
846 // std::is_copy_constructible<E>::value &&
847 // std::is_assignable<E&, E>::value )
848
849 nsel_constexpr14 expected( unexpected_type<E> const & error )
850 : has_value_( false )
851 {
852 contained.construct_error( error.value() );
853 }
854
855 // ?? expected( unexpected_type<E> && error )
856
857 template <class Err>
858 nsel_constexpr14 expected( unexpected_type<Err> const & error )
859 : has_value_( false )
860 {
861 contained.construct_error( error.value() );
862 }
863
864 // destructor
865
866 ~expected()
867 {
868 if ( ! has_value() ) contained.destruct_error();
869 }
870
871 // assignment
872
873 // nsel_REQUIRES(
874 // std::is_copy_constructible<E>::value &&
875 // std::is_copy_assignable<E>::value )
876
877 expected & operator=(expected const & rhs )
878 {
879 expected( rhs ).swap( *this );
880 return *this;
881 }
882
883 // nsel_REQUIRES(
884 // std::is_move_constructible<E>::value &&
885 // std::is_move_assignable<E>::value )
886
887 expected & operator=( expected && rhs ) noexcept
888 (
889 std::is_nothrow_move_assignable<E>::value &&
890 std::is_nothrow_move_constructible<E>::value )
891 {
892 expected( std::move( rhs ) ).swap( *this );
893 return *this;
894 }
895
896 void emplace()
897 {}
898
899 // swap
900
901 // nsel_REQUIRES(
902 // std::is_move_constructible<E>::value )
903
904 void swap( expected & rhs ) noexcept
905 (
906 std::is_nothrow_move_constructible<E>::value && noexcept( std::swap( std::declval<E&>(), std::declval<E&>() ) )
907 )
908 {
909 using std::swap;
910
911 if ( ! bool(*this) && ! bool(rhs) ) { swap( contained.error(), rhs.contained.error() ); }
912 else if ( bool(*this) && ! bool(rhs) ) { contained.construct_error( std::move( rhs.error() ) );
913 swap( has_value_, rhs.has_value_ ); }
914 else if ( ! bool(*this) && bool(rhs) ) { rhs.swap( *this ); }
915 }
916
917 // observers
918
919 constexpr explicit operator bool() const noexcept
920 {
921 return has_value();
922 }
923
924 constexpr bool has_value() const noexcept
925 {
926 return has_value_;
927 }
928
929 void value() const
930 {}
931
932 constexpr error_type const & error() const &
933 {
934 return assert( ! has_value() ), contained.error();
935 }
936
937 error_type & error() &
938 {
939 return assert( ! has_value() ), contained.error();
940 }
941
942 constexpr error_type && error() const &&
943 {
944 return assert( ! has_value() ), std::move( contained.error() );
945 }
946
947 constexpr unexpected_type<error_type> get_unexpected() const
948 {
949 return make_unexpected( contained.error() );
950 }
951
952 template <typename Ex>
953 bool has_exception() const
954 {
955 return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value;
956 }
957
958 // template constexpr \92see below\92 unwrap() const&;
959 //
960 // template \92see below\92 unwrap() &&;
961
962 // factories
963
964 // template <typename Ex, typename F>
965 // expected<void,E> catch_exception(F&& f);
966 //
967 // template <typename F>
968 // expected<decltype(func()), E> map(F&& func) ;
969 //
970 // template <typename F>
971 // \92see below\92 bind(F&& func) ;
972 //
973 // template <typename F>
974 // expected<void,E> catch_error(F&& f);
975 //
976 // template <typename F>
977 // \92see below\92 then(F&& func);
978
979 private:
980 bool has_value_;
981 expected_detail::storage_t<void,E> contained;
982 };
983
984 // expected: relational operators
985
986 template <typename T, typename E>
987 constexpr bool operator==( expected<T,E> const & x, expected<T,E> const & y )
988 {
989 return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
990 }
991
992 template <typename T, typename E>
993 constexpr bool operator!=( expected<T,E> const & x, expected<T,E> const & y )
994 {
995 return !(x == y);
996 }
997
998 template <typename T, typename E>
999 constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y )
1000 {
1001 return (!y) ? false : (!x) ? true : *x < *y;
1002 }
1003
1004 template <typename T, typename E>
1005 constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y )
1006 {
1007 return (y < x);
1008 }
1009
1010 template <typename T, typename E>
1011 constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y )
1012 {
1013 return !(y < x);
1014 }
1015
1016 template <typename T, typename E>
1017 constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y )
1018 {
1019 return !(x < y);
1020 }
1021
1022 // expected: comparison with unexpected_type
1023
1024 template <typename T, typename E>
1025 constexpr bool operator==( expected<T,E> const & x, unexpected_type<E> const & u )
1026 {
1027 return (!x) ? x.get_unexpected() == u : false;
1028 }
1029
1030 template <typename T, typename E>
1031 constexpr bool operator==( unexpected_type<E> const & u, expected<T,E> const & x )
1032 {
1033 return ( x == u );
1034 }
1035
1036 template <typename T, typename E>
1037 constexpr bool operator!=( expected<T,E> const & x, unexpected_type<E> const & u )
1038 {
1039 return ! ( x == u );
1040 }
1041
1042 template <typename T, typename E>
1043 constexpr bool operator!=( unexpected_type<E> const & u, expected<T,E> const & x )
1044 {
1045 return ! ( x == u );
1046 }
1047
1048 template <typename T, typename E>
1049 constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u )
1050 {
1051 return (!x) ? ( x.get_unexpected() < u ) : false;
1052 }
1053
1054 template <typename T, typename E>
1055 constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x )
1056 {
1057 return (!x) ? ( u < x.get_unexpected() ) : true ;
1058 }
1059
1060 template <typename T, typename E>
1061 constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u )
1062 {
1063 return ( u < x );
1064 }
1065
1066 template <typename T, typename E>
1067 constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x )
1068 {
1069 return ( x < u );
1070 }
1071
1072 template <typename T, typename E>
1073 constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u )
1074 {
1075 return ! ( u < x );
1076 }
1077
1078 template <typename T, typename E>
1079 constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x)
1080 {
1081 return ! ( x < u );
1082 }
1083
1084 template <typename T, typename E>
1085 constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u )
1086 {
1087 return ! ( u > x );
1088 }
1089
1090 template <typename T, typename E>
1091 constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x )
1092 {
1093 return ! ( x > u );
1094 }
1095
1096 // expected: comparison with T
1097
1098 template <typename T, typename E>
1099 constexpr bool operator==( expected<T,E> const & x, T const & v )
1100 {
1101 return bool(x) ? *x == v : false;
1102 }
1103
1104 template <typename T, typename E>
1105 constexpr bool operator==(T const & v, expected<T,E> const & x )
1106 {
1107 return bool(x) ? v == *x : false;
1108 }
1109
1110 template <typename T, typename E>
1111 constexpr bool operator!=( expected<T,E> const & x, T const & v )
1112 {
1113 return bool(x) ? *x != v : true;
1114 }
1115
1116 template <typename T, typename E>
1117 constexpr bool operator!=( T const & v, expected<T,E> const & x )
1118 {
1119 return bool(x) ? v != *x : true;
1120 }
1121
1122 template <typename T, typename E>
1123 constexpr bool operator<( expected<T,E> const & x, T const & v )
1124 {
1125 return bool(x) ? *x < v : true;
1126 }
1127
1128 template <typename T, typename E>
1129 constexpr bool operator<( T const & v, expected<T,E> const & x )
1130 {
1131 return bool(x) ? v < *x : false;
1132 }
1133
1134 template <typename T, typename E>
1135 constexpr bool operator>( T const & v, expected<T,E> const & x )
1136 {
1137 return bool(x) ? *x < v : false;
1138 }
1139
1140 template <typename T, typename E>
1141 constexpr bool operator>( expected<T,E> const & x, T const & v )
1142 {
1143 return bool(x) ? v < *x : false;
1144 }
1145
1146 template <typename T, typename E>
1147 constexpr bool operator<=( T const & v, expected<T,E> const & x )
1148 {
1149 return bool(x) ? ! ( *x < v ) : false;
1150 }
1151
1152 template <typename T, typename E>
1153 constexpr bool operator<=( expected<T,E> const & x, T const & v )
1154 {
1155 return bool(x) ? ! ( v < *x ) : true;
1156 }
1157
1158 template <typename T, typename E>
1159 constexpr bool operator>=( expected<T,E> const & x, T const & v )
1160 {
1161 return bool(x) ? ! ( *x < v ) : false;
1162 }
1163
1164 template <typename T, typename E>
1165 constexpr bool operator>=( T const & v, expected<T,E> const & x )
1166 {
1167 return bool(x) ? ! ( v < *x ) : true;
1168 }
1169
1170 // expected: specialized algorithms
1171
1172 template< typename T, typename E >
1173 void swap( expected<T,E> & x, expected<T,E> & y ) noexcept( noexcept( x.swap(y) ) )
1174 {
1175 x.swap( y );
1176 }
1177
1178 template< typename T>
1179 constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
1180 {
1181 return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
1182 }
1183
1184 // expected<void> specialization:
1185
1186 inline auto make_expected() -> expected<void>
1187 {
1188 return expected<void>( in_place );
1189 }
1190
1191 template< typename T, typename E >
1192 constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
1193 {
1194 return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
1195 }
1196
1197 END_OPENTRACING_ABI_NAMESPACE
1198 } // namespace opentracing
1199
1200 namespace std {
1201
1202 // expected: hash support
1203
1204 template< typename T, typename E >
1205 struct hash< opentracing::expected<T,E> >
1206 {
1207 typedef typename hash<T>::result_type result_type;
1208 typedef opentracing::expected<T,E> argument_type;
1209
1210 constexpr result_type operator()(argument_type const & arg) const
1211 {
1212 return arg ? std::hash<T>{}(*arg) : result_type{};
1213 }
1214 };
1215
1216 // TBD - ?? remove? see spec.
1217 template< typename T, typename E >
1218 struct hash< opentracing::expected<T&,E> >
1219 {
1220 typedef typename hash<T>::result_type result_type;
1221 typedef opentracing::expected<T&,E> argument_type;
1222
1223 constexpr result_type operator()(argument_type const & arg) const
1224 {
1225 return arg ? std::hash<T>{}(*arg) : result_type{};
1226 }
1227 };
1228
1229 // TBD - implement
1230 // bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true;
1231 // otherwise it evaluates to an unspecified value if E is exception_ptr or
1232 // a combination of hashing false and hash<E>()(e.error()).
1233
1234 template< typename E >
1235 struct hash< opentracing::expected<void,E> >
1236 {
1237 };
1238
1239 } // namespace std
1240
1241 #undef nsel_REQUIRES
1242 #undef nsel_REQUIRES_0
1243 #undef nsel_REQUIRES_T
1244
1245 #endif // OPENTRACING_EXPECTED_LITE_HPP