1 // Copyright (C) 2016 Martin Moene.
3 // This version targets C++11 and later.
5 // This code is licensed under the MIT License (MIT).
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.
11 #ifndef OPENTRACING_EXPECTED_LITE_HPP
12 #define OPENTRACING_EXPECTED_LITE_HPP
17 #include <initializer_list>
20 #include <type_traits>
22 #include <opentracing/version.h>
24 #define expected_lite_VERSION "0.0.0"
26 // Compiler detection:
28 #define nsel_CPP11_OR_GREATER ( __cplusplus >= 201103L )
29 #define nsel_CPP14_OR_GREATER ( __cplusplus >= 201402L )
31 #if nsel_CPP14_OR_GREATER
32 # define nsel_constexpr14 constexpr
34 # define nsel_constexpr14 /*constexpr*/
39 #define nsel_REQUIRES(...) \
40 typename std::enable_if<__VA_ARGS__, void*>::type = 0
42 #define nsel_REQUIRES_0(...) \
43 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
45 #define nsel_REQUIRES_T(...) \
46 typename = typename std::enable_if< (__VA_ARGS__), opentracing::expected_detail::enabler >::type
48 namespace opentracing {
49 BEGIN_OPENTRACING_ABI_NAMESPACE
51 template< typename T, typename E >
54 namespace expected_detail {
56 /// for nsel_REQUIRES_T
60 /// discriminated union to hold value or 'error'.
62 template< typename T, typename E >
65 friend class expected<T,E>;
75 void construct_value( value_type const & v )
77 new( &m_value ) value_type( v );
80 void construct_value( value_type && v )
82 new( &m_value ) value_type( std::forward<T>( v ) );
87 m_value.~value_type();
90 void construct_error( error_type const & e )
92 new( &m_error ) error_type( e );
95 void construct_error( error_type && e )
97 new( &m_error ) error_type( std::move( e ) );
100 void destruct_error()
102 m_error.~error_type();
105 constexpr value_type const & value() const &
110 value_type & value() &
115 constexpr value_type && value() const &&
117 return std::move( m_value );
120 const value_type * value_ptr() const
125 value_type * value_ptr()
130 error_type const & error() const
145 /// discriminated union to hold only 'error'.
147 template< typename E >
148 union storage_t<void, E>
150 friend class expected<void,E>;
153 typedef void value_type;
154 typedef E error_type;
156 // no-op construction
160 void construct_error( error_type const & e )
162 new( &m_error ) error_type( e );
165 void construct_error( error_type && e )
167 new( &m_error ) error_type( std::move( e ) );
170 void destruct_error()
172 m_error.~error_type();
175 error_type const & error() const
189 } // namespace expected_detail
191 /// class unexpected_type
193 template< typename E = std::error_code >
194 class unexpected_type
197 typedef E error_type;
199 unexpected_type() = delete;
202 std::is_copy_constructible<error_type>::value )
204 constexpr explicit unexpected_type( error_type const & error )
209 std::is_move_constructible<error_type>::value )
211 constexpr explicit unexpected_type( error_type && error )
212 : m_error( std::move( error ) )
215 constexpr error_type const & value() const
229 /// class unexpected_type, std::exception_ptr specialization
232 class unexpected_type< std::exception_ptr >
235 typedef std::exception_ptr error_type;
237 unexpected_type() = delete;
241 explicit unexpected_type( std::exception_ptr const & error )
245 explicit unexpected_type(std::exception_ptr && error )
246 : m_error( std::move( error ) )
249 template< typename E >
250 explicit unexpected_type( E error )
251 : m_error( std::make_exception_ptr( error ) )
254 std::exception_ptr const & value() const
259 std::exception_ptr & value()
265 std::exception_ptr m_error;
268 // unexpected: relational operators
270 template< typename E >
271 constexpr bool operator==( unexpected_type<E> const & x, unexpected_type<E> const & y )
273 return x.value() == y.value();
276 template< typename E >
277 constexpr bool operator!=( unexpected_type<E> const & x, unexpected_type<E> const & y )
282 template< typename E >
283 constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y )
285 return x.value() < y.value();
288 template< typename E >
289 constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y )
294 template< typename E >
295 constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y )
300 template< typename E >
301 constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y )
306 inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
311 inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
316 inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
321 inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
326 // unexpected: traits
328 template <typename E>
329 struct is_unexpected : std::false_type {};
331 template <typename E>
332 struct is_unexpected< unexpected_type<E> > : std::true_type {};
334 // unexpected: factory
336 template< typename E>
337 nsel_constexpr14 auto
338 make_unexpected( E && v) -> unexpected_type< typename std::decay<E>::type >
340 return unexpected_type< typename std::decay<E>::type >( v );
343 /*nsel_constexpr14*/ inline auto
344 make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
346 return unexpected_type< std::exception_ptr >( std::current_exception() );
349 /// in-place tag: construct a value in-place (should come from std::experimental::optional)
353 constexpr in_place_t in_place{};
355 /// unexpect tag, in_place_unexpected tag: construct an error
357 struct in_place_unexpected_t{};
359 constexpr in_place_unexpected_t unexpect{};
360 constexpr in_place_unexpected_t in_place_unexpected{};
362 /// expected access error
364 template< typename E >
365 class bad_expected_access : public std::logic_error
368 typedef E error_type;
370 explicit bad_expected_access( error_type error )
371 : logic_error( "bad_expected_access" )
375 constexpr error_type const & error() const
389 /// class error_traits
391 template< typename Error >
394 static void rethrow( Error const & e )
396 throw bad_expected_access<Error>{ e };
401 struct error_traits< std::exception_ptr >
403 static void rethrow( std::exception_ptr const & e )
405 std::rethrow_exception( e );
410 struct error_traits< std::error_code >
412 static void rethrow( std::error_code const & e )
414 throw std::system_error( e );
420 template< typename T, typename E = std::error_code >
424 typedef T value_type;
425 typedef E error_type;
430 std::is_default_constructible<T>::value )
432 nsel_constexpr14 expected() noexcept
434 std::is_nothrow_default_constructible<T>::value
438 contained.construct_value( value_type() );
442 // std::is_copy_constructible<T>::value &&
443 // std::is_copy_constructible<E>::value )
445 nsel_constexpr14 expected( expected const & rhs )
446 : has_value_( rhs.has_value_ )
448 if ( has_value() ) contained.construct_value( rhs.contained.value() );
449 else contained.construct_error( rhs.contained.error() );
453 // std::is_move_constructible<T>::value &&
454 // std::is_move_constructible<E>::value )
456 nsel_constexpr14 expected( expected && rhs )
457 : has_value_( rhs.has_value_ )
459 if ( has_value() ) contained.construct_value( std::move( rhs.contained.value() ) );
460 else contained.construct_error( std::move( rhs.contained.error() ) );
464 std::is_copy_constructible<T>::value )
466 nsel_constexpr14 expected( value_type const & rhs )
469 contained.construct_value( rhs );
473 std::is_move_constructible<T>::value )
475 nsel_constexpr14 expected( value_type && rhs ) noexcept
477 std::is_nothrow_move_constructible<T>::value &&
478 std::is_nothrow_move_constructible<E>::value
482 contained.construct_value( std::move( rhs ) );
485 template <typename... Args, nsel_REQUIRES_T(
486 std::is_constructible<T, Args&&...>::value ) >
488 nsel_constexpr14 explicit expected( in_place_t, Args&&... args )
491 contained.construct_value( std::forward<Args>( args )... );
494 template< typename U, typename... Args, nsel_REQUIRES_T(
495 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value ) >
497 nsel_constexpr14 explicit expected( in_place_t, std::initializer_list<U> il, Args&&... args )
500 contained.construct_value( il, std::forward<Args>( args )... );
504 std::is_copy_constructible<E>::value )
506 nsel_constexpr14 expected( unexpected_type<E> const & error )
507 : has_value_( false )
509 contained.construct_error( error.value() );
513 std::is_move_constructible<E>::value )
515 nsel_constexpr14 expected( unexpected_type<E> && error )
516 : has_value_( false )
518 contained.construct_error( std::move( error.value() ) );
521 template< typename... Args, nsel_REQUIRES_T(
522 std::is_constructible<E, Args&&...>::value ) >
524 nsel_constexpr14 explicit expected( in_place_unexpected_t, Args&&... args )
525 : has_value_( false )
527 contained.construct_error( std::forward<Args>( args )... );
530 template< typename U, typename... Args, nsel_REQUIRES_T(
531 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value ) >
533 nsel_constexpr14 explicit expected( in_place_unexpected_t, std::initializer_list<U> il, Args&&... args )
534 : has_value_( false )
536 contained.construct_error( il, std::forward<Args>( args )... );
543 if ( has_value() ) contained.destruct_value();
544 else contained.destruct_error();
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 )
555 expected operator=( expected const & rhs )
557 expected( rhs ).swap( *this );
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 )
567 expected & operator=( expected && rhs ) noexcept
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 )
574 expected( std::move( rhs ) ).swap( *this );
578 template< typename U, nsel_REQUIRES_T(
579 std::is_constructible<T,U>::value &&
580 std::is_assignable<T&, U>::value ) >
582 expected & operator=( U && v )
584 expected( std::forward<U>( v ) ).swap( *this );
589 // std::is_copy_constructible<E>::value &&
590 // std::is_assignable<E&, E>::value )
592 expected & operator=( unexpected_type<E> const & u )
594 expected( std::move( u ) ).swap( *this );
599 // std::is_copy_constructible<E>::value &&
600 // std::is_assignable<E&, E>::value )
602 expected & operator=( unexpected_type<E> && u )
604 expected( std::move( u ) ).swap( *this );
608 template< typename... Args, nsel_REQUIRES_T(
609 std::is_constructible<T, Args&&...>::value ) >
611 void emplace( Args &&... args )
613 expected( in_place, std::forward<Args>(args)... ).swap( *this );
616 template< typename U, typename... Args, nsel_REQUIRES_T(
617 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value ) >
619 void emplace( std::initializer_list<U> il, Args &&... args )
621 expected( in_place, il, std::forward<Args>(args)... ).swap( *this );
625 // std::is_move_constructible<T>::value &&
626 // std::is_move_constructible<E>::value )
628 void swap( expected & rhs ) noexcept
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&>() ) ) )
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 ); }
648 constexpr value_type const * operator ->() const
650 return assert( has_value() ), contained.value_ptr();
653 value_type * operator ->()
655 return assert( has_value() ), contained.value_ptr();
658 constexpr value_type const & operator *() const &
660 return assert( has_value() ), contained.value();
663 value_type & operator *() &
665 return assert( has_value() ), contained.value();
668 constexpr value_type && operator *() const &&
670 return assert( has_value() ), std::move( contained.value() );
673 value_type && operator *() &&
675 return assert( has_value() ), std::move( contained.value() );
679 constexpr explicit operator bool() const noexcept
684 constexpr bool has_value() const noexcept
689 constexpr value_type const & value() const &
692 ? ( contained.value() )
693 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
696 value_type & value() &
699 ? ( contained.value() )
700 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
703 value_type && value() &&
706 ? ( contained.value() )
707 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
710 constexpr error_type const & error() const &
712 return assert( ! has_value() ), contained.error();
715 error_type & error() &
717 return assert( ! has_value() ), contained.error();
720 constexpr error_type && error() const &&
722 return assert( ! has_value() ), std::move( contained.error() );
725 constexpr unexpected_type<E> get_unexpected() const
727 return make_unexpected( contained.error() );
730 template< typename Ex >
731 bool has_exception() const
733 return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value;
736 template< typename U, nsel_REQUIRES_T(
737 std::is_copy_constructible<T>::value &&
738 std::is_convertible<U&&, T>::value ) >
740 value_type value_or( U && v ) const &
744 : static_cast<T>( std::forward<U>( v ) );
747 template< typename U, nsel_REQUIRES_T(
748 std::is_move_constructible<T>::value &&
749 std::is_convertible<U&&, T>::value ) >
751 value_type value_or( U && v ) &&
754 ? std::move( contained.value() )
755 : static_cast<T>( std::forward<U>( v ) );
760 // template <class U, class E>
761 // constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
763 // template <class T, class E>
764 // constexpr expected<T,E> expected<T,E>::unwrap() const&;
766 // template <class U, class E>
767 // expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
769 // template <class T, class E>
770 // template expected<T,E> expected<T,E>::unwrap() &&;
774 // template <typename Ex, typename F>
775 // expected<T,E> catch_exception(F&& f);
777 // template <typename F>
778 // expected<decltype(func(declval<T>())),E> map(F&& func) ;
780 // template <typename F>
781 //
\92see below
\92 bind(F&& func);
783 // template <typename F>
784 // expected<T,E> catch_error(F&& f);
786 // template <typename F>
787 //
\92see below
\92 then(F&& func);
791 expected_detail::storage_t<T,E> contained;
794 /// class expected, void specialization
796 template< typename E >
797 class expected<void, E>
800 typedef void value_type;
801 typedef E error_type;
803 template< typename U >
806 typedef expected<U, error_type> type;
811 constexpr expected() noexcept
817 // std::is_copy_constructible<E>::value )
819 nsel_constexpr14 expected( expected const & rhs )
820 : has_value_( rhs.has_value_ )
822 if ( ! has_value() ) contained.construct_error( rhs.contained.error() );
826 std::is_move_constructible<E>::value )
828 nsel_constexpr14 expected( expected && rhs ) noexcept
830 true // TBD - see also non-void specialization
832 : has_value_( rhs.has_value_ )
834 if ( ! has_value() ) contained.construct_error( std::move( rhs.contained.error() ) );
838 // std::is_default_constructible<E>::value )
840 constexpr explicit expected( in_place_t )
846 // std::is_copy_constructible<E>::value &&
847 // std::is_assignable<E&, E>::value )
849 nsel_constexpr14 expected( unexpected_type<E> const & error )
850 : has_value_( false )
852 contained.construct_error( error.value() );
855 // ?? expected( unexpected_type<E> && error )
858 nsel_constexpr14 expected( unexpected_type<Err> const & error )
859 : has_value_( false )
861 contained.construct_error( error.value() );
868 if ( ! has_value() ) contained.destruct_error();
874 // std::is_copy_constructible<E>::value &&
875 // std::is_copy_assignable<E>::value )
877 expected & operator=(expected const & rhs )
879 expected( rhs ).swap( *this );
884 // std::is_move_constructible<E>::value &&
885 // std::is_move_assignable<E>::value )
887 expected & operator=( expected && rhs ) noexcept
889 std::is_nothrow_move_assignable<E>::value &&
890 std::is_nothrow_move_constructible<E>::value )
892 expected( std::move( rhs ) ).swap( *this );
902 // std::is_move_constructible<E>::value )
904 void swap( expected & rhs ) noexcept
906 std::is_nothrow_move_constructible<E>::value && noexcept( std::swap( std::declval<E&>(), std::declval<E&>() ) )
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 ); }
919 constexpr explicit operator bool() const noexcept
924 constexpr bool has_value() const noexcept
932 constexpr error_type const & error() const &
934 return assert( ! has_value() ), contained.error();
937 error_type & error() &
939 return assert( ! has_value() ), contained.error();
942 constexpr error_type && error() const &&
944 return assert( ! has_value() ), std::move( contained.error() );
947 constexpr unexpected_type<error_type> get_unexpected() const
949 return make_unexpected( contained.error() );
952 template <typename Ex>
953 bool has_exception() const
955 return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value;
958 // template constexpr
\92see below
\92 unwrap() const&;
960 // template
\92see below
\92 unwrap() &&;
964 // template <typename Ex, typename F>
965 // expected<void,E> catch_exception(F&& f);
967 // template <typename F>
968 // expected<decltype(func()), E> map(F&& func) ;
970 // template <typename F>
971 //
\92see below
\92 bind(F&& func) ;
973 // template <typename F>
974 // expected<void,E> catch_error(F&& f);
976 // template <typename F>
977 //
\92see below
\92 then(F&& func);
981 expected_detail::storage_t<void,E> contained;
984 // expected: relational operators
986 template <typename T, typename E>
987 constexpr bool operator==( expected<T,E> const & x, expected<T,E> const & y )
989 return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
992 template <typename T, typename E>
993 constexpr bool operator!=( expected<T,E> const & x, expected<T,E> const & y )
998 template <typename T, typename E>
999 constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y )
1001 return (!y) ? false : (!x) ? true : *x < *y;
1004 template <typename T, typename E>
1005 constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y )
1010 template <typename T, typename E>
1011 constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y )
1016 template <typename T, typename E>
1017 constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y )
1022 // expected: comparison with unexpected_type
1024 template <typename T, typename E>
1025 constexpr bool operator==( expected<T,E> const & x, unexpected_type<E> const & u )
1027 return (!x) ? x.get_unexpected() == u : false;
1030 template <typename T, typename E>
1031 constexpr bool operator==( unexpected_type<E> const & u, expected<T,E> const & x )
1036 template <typename T, typename E>
1037 constexpr bool operator!=( expected<T,E> const & x, unexpected_type<E> const & u )
1039 return ! ( x == u );
1042 template <typename T, typename E>
1043 constexpr bool operator!=( unexpected_type<E> const & u, expected<T,E> const & x )
1045 return ! ( x == u );
1048 template <typename T, typename E>
1049 constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u )
1051 return (!x) ? ( x.get_unexpected() < u ) : false;
1054 template <typename T, typename E>
1055 constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x )
1057 return (!x) ? ( u < x.get_unexpected() ) : true ;
1060 template <typename T, typename E>
1061 constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u )
1066 template <typename T, typename E>
1067 constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x )
1072 template <typename T, typename E>
1073 constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u )
1078 template <typename T, typename E>
1079 constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x)
1084 template <typename T, typename E>
1085 constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u )
1090 template <typename T, typename E>
1091 constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x )
1096 // expected: comparison with T
1098 template <typename T, typename E>
1099 constexpr bool operator==( expected<T,E> const & x, T const & v )
1101 return bool(x) ? *x == v : false;
1104 template <typename T, typename E>
1105 constexpr bool operator==(T const & v, expected<T,E> const & x )
1107 return bool(x) ? v == *x : false;
1110 template <typename T, typename E>
1111 constexpr bool operator!=( expected<T,E> const & x, T const & v )
1113 return bool(x) ? *x != v : true;
1116 template <typename T, typename E>
1117 constexpr bool operator!=( T const & v, expected<T,E> const & x )
1119 return bool(x) ? v != *x : true;
1122 template <typename T, typename E>
1123 constexpr bool operator<( expected<T,E> const & x, T const & v )
1125 return bool(x) ? *x < v : true;
1128 template <typename T, typename E>
1129 constexpr bool operator<( T const & v, expected<T,E> const & x )
1131 return bool(x) ? v < *x : false;
1134 template <typename T, typename E>
1135 constexpr bool operator>( T const & v, expected<T,E> const & x )
1137 return bool(x) ? *x < v : false;
1140 template <typename T, typename E>
1141 constexpr bool operator>( expected<T,E> const & x, T const & v )
1143 return bool(x) ? v < *x : false;
1146 template <typename T, typename E>
1147 constexpr bool operator<=( T const & v, expected<T,E> const & x )
1149 return bool(x) ? ! ( *x < v ) : false;
1152 template <typename T, typename E>
1153 constexpr bool operator<=( expected<T,E> const & x, T const & v )
1155 return bool(x) ? ! ( v < *x ) : true;
1158 template <typename T, typename E>
1159 constexpr bool operator>=( expected<T,E> const & x, T const & v )
1161 return bool(x) ? ! ( *x < v ) : false;
1164 template <typename T, typename E>
1165 constexpr bool operator>=( T const & v, expected<T,E> const & x )
1167 return bool(x) ? ! ( v < *x ) : true;
1170 // expected: specialized algorithms
1172 template< typename T, typename E >
1173 void swap( expected<T,E> & x, expected<T,E> & y ) noexcept( noexcept( x.swap(y) ) )
1178 template< typename T>
1179 constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
1181 return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
1184 // expected<void> specialization:
1186 inline auto make_expected() -> expected<void>
1188 return expected<void>( in_place );
1191 template< typename T, typename E >
1192 constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
1194 return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
1197 END_OPENTRACING_ABI_NAMESPACE
1198 } // namespace opentracing
1202 // expected: hash support
1204 template< typename T, typename E >
1205 struct hash< opentracing::expected<T,E> >
1207 typedef typename hash<T>::result_type result_type;
1208 typedef opentracing::expected<T,E> argument_type;
1210 constexpr result_type operator()(argument_type const & arg) const
1212 return arg ? std::hash<T>{}(*arg) : result_type{};
1216 // TBD - ?? remove? see spec.
1217 template< typename T, typename E >
1218 struct hash< opentracing::expected<T&,E> >
1220 typedef typename hash<T>::result_type result_type;
1221 typedef opentracing::expected<T&,E> argument_type;
1223 constexpr result_type operator()(argument_type const & arg) const
1225 return arg ? std::hash<T>{}(*arg) : result_type{};
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()).
1234 template< typename E >
1235 struct hash< opentracing::expected<void,E> >
1241 #undef nsel_REQUIRES
1242 #undef nsel_REQUIRES_0
1243 #undef nsel_REQUIRES_T
1245 #endif // OPENTRACING_EXPECTED_LITE_HPP