1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef _LIBCPP___EXPECTED_UNEXPECTED_H 10 #define _LIBCPP___EXPECTED_UNEXPECTED_H 11 12 #include <__config> 13 #include <__type_traits/conjunction.h> 14 #include <__type_traits/is_array.h> 15 #include <__type_traits/is_const.h> 16 #include <__type_traits/is_constructible.h> 17 #include <__type_traits/is_nothrow_constructible.h> 18 #include <__type_traits/is_object.h> 19 #include <__type_traits/is_same.h> 20 #include <__type_traits/is_swappable.h> 21 #include <__type_traits/is_volatile.h> 22 #include <__type_traits/negation.h> 23 #include <__type_traits/remove_cvref.h> 24 #include <__utility/forward.h> 25 #include <__utility/in_place.h> 26 #include <__utility/move.h> 27 #include <__utility/swap.h> 28 #include <initializer_list> 29 30 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 31 # pragma GCC system_header 32 #endif 33 34 _LIBCPP_PUSH_MACROS 35 #include <__undef_macros> 36 37 #if _LIBCPP_STD_VER >= 23 38 39 _LIBCPP_BEGIN_NAMESPACE_STD 40 41 template <class _Err> 42 class unexpected; 43 44 template <class _Tp> 45 struct __is_std_unexpected : false_type {}; 46 47 template <class _Err> 48 struct __is_std_unexpected<unexpected<_Err>> : true_type {}; 49 50 template <class _Tp> 51 using __valid_std_unexpected = _BoolConstant< // 52 is_object_v<_Tp> && // 53 !is_array_v<_Tp> && // 54 !__is_std_unexpected<_Tp>::value && // 55 !is_const_v<_Tp> && // 56 !is_volatile_v<_Tp> // 57 >; 58 59 template <class _Err> 60 class unexpected { 61 static_assert(__valid_std_unexpected<_Err>::value, 62 "[expected.un.general] states a program that instantiates std::unexpected for a non-object type, an " 63 "array type, a specialization of unexpected, or a cv-qualified type is ill-formed."); 64 65 public: 66 _LIBCPP_HIDE_FROM_ABI constexpr unexpected(const unexpected&) = default; 67 _LIBCPP_HIDE_FROM_ABI constexpr unexpected(unexpected&&) = default; 68 69 template <class _Error = _Err> 70 requires(!is_same_v<remove_cvref_t<_Error>, unexpected> && // 71 !is_same_v<remove_cvref_t<_Error>, in_place_t> && // 72 is_constructible_v<_Err, _Error>) 73 _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(_Error&& __error) // 74 noexcept(is_nothrow_constructible_v<_Err, _Error>) // strengthened 75 : __unex_(std::forward<_Error>(__error)) {} 76 77 template <class... _Args> 78 requires is_constructible_v<_Err, _Args...> 79 _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, _Args&&... __args) // 80 noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened 81 : __unex_(std::forward<_Args>(__args)...) {} 82 83 template <class _Up, class... _Args> 84 requires is_constructible_v<_Err, initializer_list<_Up>&, _Args...> 85 _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) // 86 noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 87 : __unex_(__il, std::forward<_Args>(__args)...) {} 88 89 _LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(const unexpected&) = default; 90 _LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(unexpected&&) = default; 91 92 _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { return __unex_; } 93 _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { return __unex_; } 94 _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { return std::move(__unex_); } 95 _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { return std::move(__unex_); } 96 97 _LIBCPP_HIDE_FROM_ABI constexpr void swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Err>) { 98 static_assert(is_swappable_v<_Err>, "unexpected::swap requires is_swappable_v<E> to be true"); 99 using std::swap; 100 swap(__unex_, __other.__unex_); 101 } 102 103 _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(unexpected& __x, unexpected& __y) noexcept(noexcept(__x.swap(__y))) 104 requires is_swappable_v<_Err> 105 { 106 __x.swap(__y); 107 } 108 109 template <class _Err2> 110 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const unexpected& __x, const unexpected<_Err2>& __y) { 111 return __x.__unex_ == __y.__unex_; 112 } 113 114 private: 115 _Err __unex_; 116 }; 117 118 template <class _Err> 119 unexpected(_Err) -> unexpected<_Err>; 120 121 _LIBCPP_END_NAMESPACE_STD 122 123 #endif // _LIBCPP_STD_VER >= 23 124 125 _LIBCPP_POP_MACROS 126 127 #endif // _LIBCPP___EXPECTED_UNEXPECTED_H 128