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