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