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_EXPECTED_H 10bdd1243dSDimitry Andric #define _LIBCPP___EXPECTED_EXPECTED_H 11bdd1243dSDimitry Andric 12bdd1243dSDimitry Andric #include <__assert> 13bdd1243dSDimitry Andric #include <__config> 14bdd1243dSDimitry Andric #include <__expected/bad_expected_access.h> 15bdd1243dSDimitry Andric #include <__expected/unexpect.h> 16bdd1243dSDimitry Andric #include <__expected/unexpected.h> 1706c3fb27SDimitry Andric #include <__functional/invoke.h> 18bdd1243dSDimitry Andric #include <__memory/addressof.h> 19bdd1243dSDimitry Andric #include <__memory/construct_at.h> 20bdd1243dSDimitry Andric #include <__type_traits/conjunction.h> 21bdd1243dSDimitry Andric #include <__type_traits/disjunction.h> 2206c3fb27SDimitry Andric #include <__type_traits/integral_constant.h> 23bdd1243dSDimitry Andric #include <__type_traits/is_assignable.h> 24bdd1243dSDimitry Andric #include <__type_traits/is_constructible.h> 25bdd1243dSDimitry Andric #include <__type_traits/is_convertible.h> 26bdd1243dSDimitry Andric #include <__type_traits/is_copy_assignable.h> 27bdd1243dSDimitry Andric #include <__type_traits/is_copy_constructible.h> 28bdd1243dSDimitry Andric #include <__type_traits/is_default_constructible.h> 29bdd1243dSDimitry Andric #include <__type_traits/is_function.h> 30bdd1243dSDimitry Andric #include <__type_traits/is_move_assignable.h> 31bdd1243dSDimitry Andric #include <__type_traits/is_move_constructible.h> 32bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h> 33bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_assignable.h> 34bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_constructible.h> 35bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_default_constructible.h> 36bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_assignable.h> 37bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_constructible.h> 38bdd1243dSDimitry Andric #include <__type_traits/is_reference.h> 39bdd1243dSDimitry Andric #include <__type_traits/is_same.h> 40bdd1243dSDimitry Andric #include <__type_traits/is_swappable.h> 41bdd1243dSDimitry Andric #include <__type_traits/is_trivially_copy_constructible.h> 42bdd1243dSDimitry Andric #include <__type_traits/is_trivially_destructible.h> 43bdd1243dSDimitry Andric #include <__type_traits/is_trivially_move_constructible.h> 44bdd1243dSDimitry Andric #include <__type_traits/is_void.h> 45bdd1243dSDimitry Andric #include <__type_traits/lazy.h> 46bdd1243dSDimitry Andric #include <__type_traits/negation.h> 47bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h> 48bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h> 4906c3fb27SDimitry Andric #include <__utility/as_const.h> 50bdd1243dSDimitry Andric #include <__utility/exception_guard.h> 51bdd1243dSDimitry Andric #include <__utility/forward.h> 52bdd1243dSDimitry Andric #include <__utility/in_place.h> 53bdd1243dSDimitry Andric #include <__utility/move.h> 54bdd1243dSDimitry Andric #include <__utility/swap.h> 5506c3fb27SDimitry Andric #include <__verbose_abort> 56bdd1243dSDimitry Andric #include <initializer_list> 57bdd1243dSDimitry Andric 58bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 59bdd1243dSDimitry Andric # pragma GCC system_header 60bdd1243dSDimitry Andric #endif 61bdd1243dSDimitry Andric 6206c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS 6306c3fb27SDimitry Andric #include <__undef_macros> 6406c3fb27SDimitry Andric 65bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 23 66bdd1243dSDimitry Andric 67bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 68bdd1243dSDimitry Andric 6906c3fb27SDimitry Andric template <class _Tp, class _Err> 7006c3fb27SDimitry Andric class expected; 7106c3fb27SDimitry Andric 7206c3fb27SDimitry Andric template <class _Tp> 7306c3fb27SDimitry Andric struct __is_std_expected : false_type {}; 7406c3fb27SDimitry Andric 7506c3fb27SDimitry Andric template <class _Tp, class _Err> 7606c3fb27SDimitry Andric struct __is_std_expected<expected<_Tp, _Err>> : true_type {}; 7706c3fb27SDimitry Andric 7806c3fb27SDimitry Andric struct __expected_construct_in_place_from_invoke_tag {}; 7906c3fb27SDimitry Andric struct __expected_construct_unexpected_from_invoke_tag {}; 80bdd1243dSDimitry Andric 81bdd1243dSDimitry Andric template <class _Err, class _Arg> 82bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) { 8306c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 84bdd1243dSDimitry Andric throw bad_expected_access<_Err>(std::forward<_Arg>(__arg)); 85bdd1243dSDimitry Andric # else 86bdd1243dSDimitry Andric (void)__arg; 8706c3fb27SDimitry Andric _LIBCPP_VERBOSE_ABORT("bad_expected_access was thrown in -fno-exceptions mode"); 88bdd1243dSDimitry Andric # endif 89bdd1243dSDimitry Andric } 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric template <class _Tp, class _Err> 92bdd1243dSDimitry Andric class expected { 93bdd1243dSDimitry Andric static_assert( 94bdd1243dSDimitry Andric !is_reference_v<_Tp> && 95bdd1243dSDimitry Andric !is_function_v<_Tp> && 96bdd1243dSDimitry Andric !is_same_v<remove_cv_t<_Tp>, in_place_t> && 97bdd1243dSDimitry Andric !is_same_v<remove_cv_t<_Tp>, unexpect_t> && 98bdd1243dSDimitry Andric !__is_std_unexpected<remove_cv_t<_Tp>>::value && 99bdd1243dSDimitry Andric __valid_std_unexpected<_Err>::value 100bdd1243dSDimitry Andric , 101bdd1243dSDimitry Andric "[expected.object.general] A program that instantiates the definition of template expected<T, E> for a " 102bdd1243dSDimitry Andric "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a " 103bdd1243dSDimitry Andric "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the " 104bdd1243dSDimitry Andric "definition of the template expected<T, E> with a type for the E parameter that is not a valid " 105bdd1243dSDimitry Andric "template argument for unexpected is ill-formed."); 106bdd1243dSDimitry Andric 107bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 108bdd1243dSDimitry Andric friend class expected; 109bdd1243dSDimitry Andric 110bdd1243dSDimitry Andric public: 111bdd1243dSDimitry Andric using value_type = _Tp; 112bdd1243dSDimitry Andric using error_type = _Err; 113bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 114bdd1243dSDimitry Andric 115bdd1243dSDimitry Andric template <class _Up> 116bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric // [expected.object.ctor], constructors 119bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() 120bdd1243dSDimitry Andric noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened 121bdd1243dSDimitry Andric requires is_default_constructible_v<_Tp> 122*b121cb00SDimitry Andric : __union_(std::in_place), __has_val_(true) {} 123bdd1243dSDimitry Andric 124bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 125bdd1243dSDimitry Andric 126bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 127bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Tp> && 128bdd1243dSDimitry Andric is_copy_constructible_v<_Err> && 129bdd1243dSDimitry Andric is_trivially_copy_constructible_v<_Tp> && 130bdd1243dSDimitry Andric is_trivially_copy_constructible_v<_Err>) 131bdd1243dSDimitry Andric = default; 132bdd1243dSDimitry Andric 133bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) 134bdd1243dSDimitry Andric noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened 135bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && 136bdd1243dSDimitry Andric !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)) 137*b121cb00SDimitry Andric : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) { } 138bdd1243dSDimitry Andric 139bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 140bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> 141bdd1243dSDimitry Andric && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>) 142bdd1243dSDimitry Andric = default; 143bdd1243dSDimitry Andric 144bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) 145bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) 146bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && 147bdd1243dSDimitry Andric !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)) 148*b121cb00SDimitry Andric : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) { } 149bdd1243dSDimitry Andric 150bdd1243dSDimitry Andric private: 151bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual> 152bdd1243dSDimitry Andric using __can_convert = 153bdd1243dSDimitry Andric _And< is_constructible<_Tp, _UfQual>, 154bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 155bdd1243dSDimitry Andric _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>, 156bdd1243dSDimitry Andric _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>, 157bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>, 158bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>, 159bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>, 160bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>, 161bdd1243dSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>, 162bdd1243dSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>, 163bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 164bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 165bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 166bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >; 167bdd1243dSDimitry Andric 16806c3fb27SDimitry Andric template <class _Func, class... _Args> 16906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 17006c3fb27SDimitry Andric std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 17106c3fb27SDimitry Andric : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(true) {} 17206c3fb27SDimitry Andric 17306c3fb27SDimitry Andric template <class _Func, class... _Args> 17406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 17506c3fb27SDimitry Andric std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 17606c3fb27SDimitry Andric : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} 177bdd1243dSDimitry Andric 178bdd1243dSDimitry Andric public: 179bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 180bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value 181bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> || 182bdd1243dSDimitry Andric !is_convertible_v<const _OtherErr&, _Err>) 183bdd1243dSDimitry Andric expected(const expected<_Up, _OtherErr>& __other) 184bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, const _Up&> && 185bdd1243dSDimitry Andric is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 186*b121cb00SDimitry Andric : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {} 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 189bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value 190bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>) 191bdd1243dSDimitry Andric expected(expected<_Up, _OtherErr>&& __other) 192bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 193*b121cb00SDimitry Andric : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {} 194bdd1243dSDimitry Andric 195bdd1243dSDimitry Andric template <class _Up = _Tp> 196bdd1243dSDimitry Andric requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> && 197bdd1243dSDimitry Andric !__is_std_unexpected<remove_cvref_t<_Up>>::value && is_constructible_v<_Tp, _Up>) 198bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>) 199*b121cb00SDimitry Andric expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened 200*b121cb00SDimitry Andric : __union_(std::in_place, std::forward<_Up>(__u)), __has_val_(true) {} 201bdd1243dSDimitry Andric 202bdd1243dSDimitry Andric 203bdd1243dSDimitry Andric template <class _OtherErr> 204bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 205bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 206bdd1243dSDimitry Andric expected(const unexpected<_OtherErr>& __unex) 207bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 208*b121cb00SDimitry Andric : __union_(std::unexpect, __unex.error()), __has_val_(false) {} 209bdd1243dSDimitry Andric 210bdd1243dSDimitry Andric template <class _OtherErr> 211bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 212bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 213bdd1243dSDimitry Andric expected(unexpected<_OtherErr>&& __unex) 214bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 215*b121cb00SDimitry Andric : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {} 216bdd1243dSDimitry Andric 217bdd1243dSDimitry Andric template <class... _Args> 218bdd1243dSDimitry Andric requires is_constructible_v<_Tp, _Args...> 219bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) 220bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened 221*b121cb00SDimitry Andric : __union_(std::in_place, std::forward<_Args>(__args)...), __has_val_(true) {} 222bdd1243dSDimitry Andric 223bdd1243dSDimitry Andric template <class _Up, class... _Args> 224bdd1243dSDimitry Andric requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... > 225bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit 226bdd1243dSDimitry Andric expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 227bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened 228*b121cb00SDimitry Andric : __union_(std::in_place, __il, std::forward<_Args>(__args)...), __has_val_(true) {} 229bdd1243dSDimitry Andric 230bdd1243dSDimitry Andric template <class... _Args> 231bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 232bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) 233bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened 234*b121cb00SDimitry Andric : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {} 235bdd1243dSDimitry Andric 236bdd1243dSDimitry Andric template <class _Up, class... _Args> 237bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 238bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit 239bdd1243dSDimitry Andric expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) 240bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 241*b121cb00SDimitry Andric : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {} 242bdd1243dSDimitry Andric 243bdd1243dSDimitry Andric // [expected.object.dtor], destructor 244bdd1243dSDimitry Andric 245bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 246bdd1243dSDimitry Andric requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) 247bdd1243dSDimitry Andric = default; 248bdd1243dSDimitry Andric 249bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 250bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) 251bdd1243dSDimitry Andric { 252bdd1243dSDimitry Andric if (__has_val_) { 253bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 254bdd1243dSDimitry Andric } else { 255bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 256bdd1243dSDimitry Andric } 257bdd1243dSDimitry Andric } 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric private: 260bdd1243dSDimitry Andric template <class _T1, class _T2, class... _Args> 261bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) { 262bdd1243dSDimitry Andric if constexpr (is_nothrow_constructible_v<_T1, _Args...>) { 263bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 264bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); 265bdd1243dSDimitry Andric } else if constexpr (is_nothrow_move_constructible_v<_T1>) { 266bdd1243dSDimitry Andric _T1 __tmp(std::forward<_Args>(__args)...); 267bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 268bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::move(__tmp)); 269bdd1243dSDimitry Andric } else { 270bdd1243dSDimitry Andric static_assert( 271bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_T2>, 272bdd1243dSDimitry Andric "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can " 273bdd1243dSDimitry Andric "be reverted to the previous state in case an exception is thrown during the assignment."); 274bdd1243dSDimitry Andric _T2 __tmp(std::move(__oldval)); 275bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 2761ac55f4cSDimitry Andric auto __trans = 2771ac55f4cSDimitry Andric std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); 278bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); 279bdd1243dSDimitry Andric __trans.__complete(); 280bdd1243dSDimitry Andric } 281bdd1243dSDimitry Andric } 282bdd1243dSDimitry Andric 283bdd1243dSDimitry Andric public: 284bdd1243dSDimitry Andric // [expected.object.assign], assignment 285bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 286bdd1243dSDimitry Andric 287bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) 288bdd1243dSDimitry Andric noexcept(is_nothrow_copy_assignable_v<_Tp> && 289bdd1243dSDimitry Andric is_nothrow_copy_constructible_v<_Tp> && 290bdd1243dSDimitry Andric is_nothrow_copy_assignable_v<_Err> && 291bdd1243dSDimitry Andric is_nothrow_copy_constructible_v<_Err>) // strengthened 292bdd1243dSDimitry Andric requires(is_copy_assignable_v<_Tp> && 293bdd1243dSDimitry Andric is_copy_constructible_v<_Tp> && 294bdd1243dSDimitry Andric is_copy_assignable_v<_Err> && 295bdd1243dSDimitry Andric is_copy_constructible_v<_Err> && 296bdd1243dSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || 297bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 298bdd1243dSDimitry Andric { 299bdd1243dSDimitry Andric if (__has_val_ && __rhs.__has_val_) { 300bdd1243dSDimitry Andric __union_.__val_ = __rhs.__union_.__val_; 301bdd1243dSDimitry Andric } else if (__has_val_) { 302bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_); 303bdd1243dSDimitry Andric } else if (__rhs.__has_val_) { 304bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_); 305bdd1243dSDimitry Andric } else { 306bdd1243dSDimitry Andric __union_.__unex_ = __rhs.__union_.__unex_; 307bdd1243dSDimitry Andric } 308bdd1243dSDimitry Andric // note: only reached if no exception+rollback was done inside __reinit_expected 309bdd1243dSDimitry Andric __has_val_ = __rhs.__has_val_; 310bdd1243dSDimitry Andric return *this; 311bdd1243dSDimitry Andric } 312bdd1243dSDimitry Andric 313bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) 314bdd1243dSDimitry Andric noexcept(is_nothrow_move_assignable_v<_Tp> && 315bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Tp> && 316bdd1243dSDimitry Andric is_nothrow_move_assignable_v<_Err> && 317bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>) 318bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && 319bdd1243dSDimitry Andric is_move_assignable_v<_Tp> && 320bdd1243dSDimitry Andric is_move_constructible_v<_Err> && 321bdd1243dSDimitry Andric is_move_assignable_v<_Err> && 322bdd1243dSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || 323bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 324bdd1243dSDimitry Andric { 325bdd1243dSDimitry Andric if (__has_val_ && __rhs.__has_val_) { 326bdd1243dSDimitry Andric __union_.__val_ = std::move(__rhs.__union_.__val_); 327bdd1243dSDimitry Andric } else if (__has_val_) { 328bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_)); 329bdd1243dSDimitry Andric } else if (__rhs.__has_val_) { 330bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_)); 331bdd1243dSDimitry Andric } else { 332bdd1243dSDimitry Andric __union_.__unex_ = std::move(__rhs.__union_.__unex_); 333bdd1243dSDimitry Andric } 334bdd1243dSDimitry Andric // note: only reached if no exception+rollback was done inside __reinit_expected 335bdd1243dSDimitry Andric __has_val_ = __rhs.__has_val_; 336bdd1243dSDimitry Andric return *this; 337bdd1243dSDimitry Andric } 338bdd1243dSDimitry Andric 339bdd1243dSDimitry Andric template <class _Up = _Tp> 340bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v) 341bdd1243dSDimitry Andric requires(!is_same_v<expected, remove_cvref_t<_Up>> && 342bdd1243dSDimitry Andric !__is_std_unexpected<remove_cvref_t<_Up>>::value && 343bdd1243dSDimitry Andric is_constructible_v<_Tp, _Up> && 344bdd1243dSDimitry Andric is_assignable_v<_Tp&, _Up> && 345bdd1243dSDimitry Andric (is_nothrow_constructible_v<_Tp, _Up> || 346bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Tp> || 347bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 348bdd1243dSDimitry Andric { 349bdd1243dSDimitry Andric if (__has_val_) { 350bdd1243dSDimitry Andric __union_.__val_ = std::forward<_Up>(__v); 351bdd1243dSDimitry Andric } else { 352bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v)); 353bdd1243dSDimitry Andric __has_val_ = true; 354bdd1243dSDimitry Andric } 355bdd1243dSDimitry Andric return *this; 356bdd1243dSDimitry Andric } 357bdd1243dSDimitry Andric 358bdd1243dSDimitry Andric private: 359bdd1243dSDimitry Andric template <class _OtherErrQual> 360bdd1243dSDimitry Andric static constexpr bool __can_assign_from_unexpected = 361bdd1243dSDimitry Andric _And< is_constructible<_Err, _OtherErrQual>, 362bdd1243dSDimitry Andric is_assignable<_Err&, _OtherErrQual>, 363bdd1243dSDimitry Andric _Lazy<_Or, 364bdd1243dSDimitry Andric is_nothrow_constructible<_Err, _OtherErrQual>, 365bdd1243dSDimitry Andric is_nothrow_move_constructible<_Tp>, 366bdd1243dSDimitry Andric is_nothrow_move_constructible<_Err>> >::value; 367bdd1243dSDimitry Andric 368bdd1243dSDimitry Andric public: 369bdd1243dSDimitry Andric template <class _OtherErr> 370bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<const _OtherErr&>) 371bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 372bdd1243dSDimitry Andric if (__has_val_) { 373bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, __un.error()); 374bdd1243dSDimitry Andric __has_val_ = false; 375bdd1243dSDimitry Andric } else { 376bdd1243dSDimitry Andric __union_.__unex_ = __un.error(); 377bdd1243dSDimitry Andric } 378bdd1243dSDimitry Andric return *this; 379bdd1243dSDimitry Andric } 380bdd1243dSDimitry Andric 381bdd1243dSDimitry Andric template <class _OtherErr> 382bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<_OtherErr>) 383bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 384bdd1243dSDimitry Andric if (__has_val_) { 385bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error())); 386bdd1243dSDimitry Andric __has_val_ = false; 387bdd1243dSDimitry Andric } else { 388bdd1243dSDimitry Andric __union_.__unex_ = std::move(__un.error()); 389bdd1243dSDimitry Andric } 390bdd1243dSDimitry Andric return *this; 391bdd1243dSDimitry Andric } 392bdd1243dSDimitry Andric 393bdd1243dSDimitry Andric template <class... _Args> 394bdd1243dSDimitry Andric requires is_nothrow_constructible_v<_Tp, _Args...> 395bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept { 396bdd1243dSDimitry Andric if (__has_val_) { 397bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 398bdd1243dSDimitry Andric } else { 399bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 400bdd1243dSDimitry Andric } 401*b121cb00SDimitry Andric std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...); 402*b121cb00SDimitry Andric __has_val_ = true; 403*b121cb00SDimitry Andric return __union_.__val_; 404bdd1243dSDimitry Andric } 405bdd1243dSDimitry Andric 406bdd1243dSDimitry Andric template <class _Up, class... _Args> 407bdd1243dSDimitry Andric requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... > 408bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept { 409bdd1243dSDimitry Andric if (__has_val_) { 410bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 411bdd1243dSDimitry Andric } else { 412bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 413bdd1243dSDimitry Andric } 414*b121cb00SDimitry Andric std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...); 415*b121cb00SDimitry Andric __has_val_ = true; 416*b121cb00SDimitry Andric return __union_.__val_; 417bdd1243dSDimitry Andric } 418bdd1243dSDimitry Andric 419bdd1243dSDimitry Andric 420bdd1243dSDimitry Andric public: 421bdd1243dSDimitry Andric // [expected.object.swap], swap 422bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) 423bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Tp> && 424bdd1243dSDimitry Andric is_nothrow_swappable_v<_Tp> && 425bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err> && 426bdd1243dSDimitry Andric is_nothrow_swappable_v<_Err>) 427bdd1243dSDimitry Andric requires(is_swappable_v<_Tp> && 428bdd1243dSDimitry Andric is_swappable_v<_Err> && 429bdd1243dSDimitry Andric is_move_constructible_v<_Tp> && 430bdd1243dSDimitry Andric is_move_constructible_v<_Err> && 431bdd1243dSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || 432bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 433bdd1243dSDimitry Andric { 434bdd1243dSDimitry Andric auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { 435bdd1243dSDimitry Andric if constexpr (is_nothrow_move_constructible_v<_Err>) { 436bdd1243dSDimitry Andric _Err __tmp(std::move(__with_err.__union_.__unex_)); 437bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 4381ac55f4cSDimitry Andric auto __trans = std::__make_exception_guard([&] { 439bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp)); 440bdd1243dSDimitry Andric }); 441bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_)); 442bdd1243dSDimitry Andric __trans.__complete(); 443bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_val.__union_.__val_)); 444bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp)); 445bdd1243dSDimitry Andric } else { 446bdd1243dSDimitry Andric static_assert(is_nothrow_move_constructible_v<_Tp>, 447bdd1243dSDimitry Andric "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so " 448bdd1243dSDimitry Andric "that it can be reverted to the previous state in case an exception is thrown during swap."); 449bdd1243dSDimitry Andric _Tp __tmp(std::move(__with_val.__union_.__val_)); 450bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_val.__union_.__val_)); 4511ac55f4cSDimitry Andric auto __trans = std::__make_exception_guard([&] { 452bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); 453bdd1243dSDimitry Andric }); 454bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); 455bdd1243dSDimitry Andric __trans.__complete(); 456bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 457bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp)); 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric __with_val.__has_val_ = false; 460bdd1243dSDimitry Andric __with_err.__has_val_ = true; 461bdd1243dSDimitry Andric }; 462bdd1243dSDimitry Andric 463bdd1243dSDimitry Andric if (__has_val_) { 464bdd1243dSDimitry Andric if (__rhs.__has_val_) { 465bdd1243dSDimitry Andric using std::swap; 466bdd1243dSDimitry Andric swap(__union_.__val_, __rhs.__union_.__val_); 467bdd1243dSDimitry Andric } else { 468bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 469bdd1243dSDimitry Andric } 470bdd1243dSDimitry Andric } else { 471bdd1243dSDimitry Andric if (__rhs.__has_val_) { 472bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 473bdd1243dSDimitry Andric } else { 474bdd1243dSDimitry Andric using std::swap; 475bdd1243dSDimitry Andric swap(__union_.__unex_, __rhs.__union_.__unex_); 476bdd1243dSDimitry Andric } 477bdd1243dSDimitry Andric } 478bdd1243dSDimitry Andric } 479bdd1243dSDimitry Andric 480bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) 481bdd1243dSDimitry Andric noexcept(noexcept(__x.swap(__y))) 482bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 483bdd1243dSDimitry Andric { 484bdd1243dSDimitry Andric __x.swap(__y); 485bdd1243dSDimitry Andric } 486bdd1243dSDimitry Andric 487bdd1243dSDimitry Andric // [expected.object.obs], observers 488bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { 48906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); 490bdd1243dSDimitry Andric return std::addressof(__union_.__val_); 491bdd1243dSDimitry Andric } 492bdd1243dSDimitry Andric 493bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { 49406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); 495bdd1243dSDimitry Andric return std::addressof(__union_.__val_); 496bdd1243dSDimitry Andric } 497bdd1243dSDimitry Andric 498bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { 49906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 500bdd1243dSDimitry Andric return __union_.__val_; 501bdd1243dSDimitry Andric } 502bdd1243dSDimitry Andric 503bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { 50406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 505bdd1243dSDimitry Andric return __union_.__val_; 506bdd1243dSDimitry Andric } 507bdd1243dSDimitry Andric 508bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { 50906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 510bdd1243dSDimitry Andric return std::move(__union_.__val_); 511bdd1243dSDimitry Andric } 512bdd1243dSDimitry Andric 513bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { 51406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 515bdd1243dSDimitry Andric return std::move(__union_.__val_); 516bdd1243dSDimitry Andric } 517bdd1243dSDimitry Andric 518bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } 519bdd1243dSDimitry Andric 520bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } 521bdd1243dSDimitry Andric 522bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { 52306c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 524bdd1243dSDimitry Andric if (!__has_val_) { 52506c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::as_const(error())); 526bdd1243dSDimitry Andric } 527bdd1243dSDimitry Andric return __union_.__val_; 528bdd1243dSDimitry Andric } 529bdd1243dSDimitry Andric 530bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { 53106c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 532bdd1243dSDimitry Andric if (!__has_val_) { 53306c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::as_const(error())); 534bdd1243dSDimitry Andric } 535bdd1243dSDimitry Andric return __union_.__val_; 536bdd1243dSDimitry Andric } 537bdd1243dSDimitry Andric 538bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { 53906c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, 54006c3fb27SDimitry Andric "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); 541bdd1243dSDimitry Andric if (!__has_val_) { 54206c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(error())); 543bdd1243dSDimitry Andric } 544bdd1243dSDimitry Andric return std::move(__union_.__val_); 545bdd1243dSDimitry Andric } 546bdd1243dSDimitry Andric 547bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { 54806c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, 54906c3fb27SDimitry Andric "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); 550bdd1243dSDimitry Andric if (!__has_val_) { 55106c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(error())); 552bdd1243dSDimitry Andric } 553bdd1243dSDimitry Andric return std::move(__union_.__val_); 554bdd1243dSDimitry Andric } 555bdd1243dSDimitry Andric 556bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 55706c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 558bdd1243dSDimitry Andric return __union_.__unex_; 559bdd1243dSDimitry Andric } 560bdd1243dSDimitry Andric 561bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 56206c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 563bdd1243dSDimitry Andric return __union_.__unex_; 564bdd1243dSDimitry Andric } 565bdd1243dSDimitry Andric 566bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 56706c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 568bdd1243dSDimitry Andric return std::move(__union_.__unex_); 569bdd1243dSDimitry Andric } 570bdd1243dSDimitry Andric 571bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 57206c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 573bdd1243dSDimitry Andric return std::move(__union_.__unex_); 574bdd1243dSDimitry Andric } 575bdd1243dSDimitry Andric 576bdd1243dSDimitry Andric template <class _Up> 577bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { 578bdd1243dSDimitry Andric static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); 579bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 580bdd1243dSDimitry Andric return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v)); 581bdd1243dSDimitry Andric } 582bdd1243dSDimitry Andric 583bdd1243dSDimitry Andric template <class _Up> 584bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { 585bdd1243dSDimitry Andric static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); 586bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 587bdd1243dSDimitry Andric return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v)); 588bdd1243dSDimitry Andric } 589bdd1243dSDimitry Andric 59006c3fb27SDimitry Andric template <class _Up = _Err> 59106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { 59206c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 59306c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 59406c3fb27SDimitry Andric if (has_value()) 59506c3fb27SDimitry Andric return std::forward<_Up>(__error); 59606c3fb27SDimitry Andric return error(); 59706c3fb27SDimitry Andric } 59806c3fb27SDimitry Andric 59906c3fb27SDimitry Andric template <class _Up = _Err> 60006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { 60106c3fb27SDimitry Andric static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); 60206c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 60306c3fb27SDimitry Andric if (has_value()) 60406c3fb27SDimitry Andric return std::forward<_Up>(__error); 60506c3fb27SDimitry Andric return std::move(error()); 60606c3fb27SDimitry Andric } 60706c3fb27SDimitry Andric 60806c3fb27SDimitry Andric // [expected.void.monadic], monadic 60906c3fb27SDimitry Andric template <class _Func> 61006c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 61106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { 61206c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>; 61306c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); 61406c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 61506c3fb27SDimitry Andric "The result of f(value()) must have the same error_type as this expected"); 61606c3fb27SDimitry Andric if (has_value()) { 61706c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 61806c3fb27SDimitry Andric } 61906c3fb27SDimitry Andric return _Up(unexpect, error()); 62006c3fb27SDimitry Andric } 62106c3fb27SDimitry Andric 62206c3fb27SDimitry Andric template <class _Func> 62306c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 62406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { 62506c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>; 62606c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); 62706c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 62806c3fb27SDimitry Andric "The result of f(value()) must have the same error_type as this expected"); 62906c3fb27SDimitry Andric if (has_value()) { 63006c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 63106c3fb27SDimitry Andric } 63206c3fb27SDimitry Andric return _Up(unexpect, error()); 63306c3fb27SDimitry Andric } 63406c3fb27SDimitry Andric 63506c3fb27SDimitry Andric template <class _Func> 63606c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 63706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { 63806c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>; 63906c3fb27SDimitry Andric static_assert( 64006c3fb27SDimitry Andric __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); 64106c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 64206c3fb27SDimitry Andric "The result of f(std::move(value())) must have the same error_type as this expected"); 64306c3fb27SDimitry Andric if (has_value()) { 64406c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 64506c3fb27SDimitry Andric } 64606c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 64706c3fb27SDimitry Andric } 64806c3fb27SDimitry Andric 64906c3fb27SDimitry Andric template <class _Func> 65006c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 65106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 65206c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>; 65306c3fb27SDimitry Andric static_assert( 65406c3fb27SDimitry Andric __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); 65506c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 65606c3fb27SDimitry Andric "The result of f(std::move(value())) must have the same error_type as this expected"); 65706c3fb27SDimitry Andric if (has_value()) { 65806c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 65906c3fb27SDimitry Andric } 66006c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 66106c3fb27SDimitry Andric } 66206c3fb27SDimitry Andric 66306c3fb27SDimitry Andric template <class _Func> 66406c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&> 66506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { 66606c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; 66706c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 66806c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 66906c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 67006c3fb27SDimitry Andric if (has_value()) { 67106c3fb27SDimitry Andric return _Gp(in_place, value()); 67206c3fb27SDimitry Andric } 67306c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 67406c3fb27SDimitry Andric } 67506c3fb27SDimitry Andric 67606c3fb27SDimitry Andric template <class _Func> 67706c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&> 67806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { 67906c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; 68006c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 68106c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 68206c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 68306c3fb27SDimitry Andric if (has_value()) { 68406c3fb27SDimitry Andric return _Gp(in_place, value()); 68506c3fb27SDimitry Andric } 68606c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 68706c3fb27SDimitry Andric } 68806c3fb27SDimitry Andric 68906c3fb27SDimitry Andric template <class _Func> 69006c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&&> 69106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { 69206c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; 69306c3fb27SDimitry Andric static_assert( 69406c3fb27SDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 69506c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 69606c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 69706c3fb27SDimitry Andric if (has_value()) { 69806c3fb27SDimitry Andric return _Gp(in_place, std::move(value())); 69906c3fb27SDimitry Andric } 70006c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 70106c3fb27SDimitry Andric } 70206c3fb27SDimitry Andric 70306c3fb27SDimitry Andric template <class _Func> 70406c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&&> 70506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { 70606c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; 70706c3fb27SDimitry Andric static_assert( 70806c3fb27SDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 70906c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 71006c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 71106c3fb27SDimitry Andric if (has_value()) { 71206c3fb27SDimitry Andric return _Gp(in_place, std::move(value())); 71306c3fb27SDimitry Andric } 71406c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 71506c3fb27SDimitry Andric } 71606c3fb27SDimitry Andric 71706c3fb27SDimitry Andric template <class _Func> 71806c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 71906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { 72006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>; 72106c3fb27SDimitry Andric if (!has_value()) { 72206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 72306c3fb27SDimitry Andric } 72406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 72506c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); 72606c3fb27SDimitry Andric } else { 72706c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f), value()); 72806c3fb27SDimitry Andric return expected<_Up, _Err>(); 72906c3fb27SDimitry Andric } 73006c3fb27SDimitry Andric } 73106c3fb27SDimitry Andric 73206c3fb27SDimitry Andric template <class _Func> 73306c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 73406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { 73506c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>; 73606c3fb27SDimitry Andric if (!has_value()) { 73706c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 73806c3fb27SDimitry Andric } 73906c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 74006c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); 74106c3fb27SDimitry Andric } else { 74206c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f), value()); 74306c3fb27SDimitry Andric return expected<_Up, _Err>(); 74406c3fb27SDimitry Andric } 74506c3fb27SDimitry Andric } 74606c3fb27SDimitry Andric 74706c3fb27SDimitry Andric template <class _Func> 74806c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 74906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { 75006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>; 75106c3fb27SDimitry Andric if (!has_value()) { 75206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 75306c3fb27SDimitry Andric } 75406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 75506c3fb27SDimitry Andric return expected<_Up, _Err>( 75606c3fb27SDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 75706c3fb27SDimitry Andric } else { 75806c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f), std::move(value())); 75906c3fb27SDimitry Andric return expected<_Up, _Err>(); 76006c3fb27SDimitry Andric } 76106c3fb27SDimitry Andric } 76206c3fb27SDimitry Andric 76306c3fb27SDimitry Andric template <class _Func> 76406c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 76506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { 76606c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>; 76706c3fb27SDimitry Andric if (!has_value()) { 76806c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 76906c3fb27SDimitry Andric } 77006c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 77106c3fb27SDimitry Andric return expected<_Up, _Err>( 77206c3fb27SDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 77306c3fb27SDimitry Andric } else { 77406c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f), std::move(value())); 77506c3fb27SDimitry Andric return expected<_Up, _Err>(); 77606c3fb27SDimitry Andric } 77706c3fb27SDimitry Andric } 77806c3fb27SDimitry Andric 77906c3fb27SDimitry Andric template <class _Func> 78006c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&> 78106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { 78206c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; 78306c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 78406c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 78506c3fb27SDimitry Andric if (has_value()) { 78606c3fb27SDimitry Andric return expected<_Tp, _Gp>(in_place, value()); 78706c3fb27SDimitry Andric } 78806c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 78906c3fb27SDimitry Andric } 79006c3fb27SDimitry Andric 79106c3fb27SDimitry Andric template <class _Func> 79206c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&> 79306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { 79406c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; 79506c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 79606c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 79706c3fb27SDimitry Andric if (has_value()) { 79806c3fb27SDimitry Andric return expected<_Tp, _Gp>(in_place, value()); 79906c3fb27SDimitry Andric } 80006c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 80106c3fb27SDimitry Andric } 80206c3fb27SDimitry Andric 80306c3fb27SDimitry Andric template <class _Func> 80406c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&&> 80506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { 80606c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; 80706c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 80806c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 80906c3fb27SDimitry Andric if (has_value()) { 81006c3fb27SDimitry Andric return expected<_Tp, _Gp>(in_place, std::move(value())); 81106c3fb27SDimitry Andric } 81206c3fb27SDimitry Andric return expected<_Tp, _Gp>( 81306c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 81406c3fb27SDimitry Andric } 81506c3fb27SDimitry Andric 81606c3fb27SDimitry Andric template <class _Func> 81706c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&&> 81806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { 81906c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; 82006c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 82106c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 82206c3fb27SDimitry Andric if (has_value()) { 82306c3fb27SDimitry Andric return expected<_Tp, _Gp>(in_place, std::move(value())); 82406c3fb27SDimitry Andric } 82506c3fb27SDimitry Andric return expected<_Tp, _Gp>( 82606c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 82706c3fb27SDimitry Andric } 82806c3fb27SDimitry Andric 829bdd1243dSDimitry Andric // [expected.object.eq], equality operators 830bdd1243dSDimitry Andric template <class _T2, class _E2> 831bdd1243dSDimitry Andric requires(!is_void_v<_T2>) 832bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 833bdd1243dSDimitry Andric if (__x.__has_val_ != __y.__has_val_) { 834bdd1243dSDimitry Andric return false; 835bdd1243dSDimitry Andric } else { 836bdd1243dSDimitry Andric if (__x.__has_val_) { 837bdd1243dSDimitry Andric return __x.__union_.__val_ == __y.__union_.__val_; 838bdd1243dSDimitry Andric } else { 839bdd1243dSDimitry Andric return __x.__union_.__unex_ == __y.__union_.__unex_; 840bdd1243dSDimitry Andric } 841bdd1243dSDimitry Andric } 842bdd1243dSDimitry Andric } 843bdd1243dSDimitry Andric 844bdd1243dSDimitry Andric template <class _T2> 845bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { 846bdd1243dSDimitry Andric return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v); 847bdd1243dSDimitry Andric } 848bdd1243dSDimitry Andric 849bdd1243dSDimitry Andric template <class _E2> 850bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { 851bdd1243dSDimitry Andric return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error()); 852bdd1243dSDimitry Andric } 853bdd1243dSDimitry Andric 854bdd1243dSDimitry Andric private: 85506c3fb27SDimitry Andric template <class _ValueType, class _ErrorType> 85606c3fb27SDimitry Andric union __union_t { 857*b121cb00SDimitry Andric template <class... _Args> 858*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args) 859*b121cb00SDimitry Andric : __val_(std::forward<_Args>(__args)...) {} 860*b121cb00SDimitry Andric 861*b121cb00SDimitry Andric template <class... _Args> 862*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 863*b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 86406c3fb27SDimitry Andric 86506c3fb27SDimitry Andric template <class _Func, class... _Args> 86606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 86706c3fb27SDimitry Andric std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) 86806c3fb27SDimitry Andric : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 86906c3fb27SDimitry Andric 87006c3fb27SDimitry Andric template <class _Func, class... _Args> 87106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 87206c3fb27SDimitry Andric std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 87306c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 874bdd1243dSDimitry Andric 875*b121cb00SDimitry Andric template <class _Union> 876*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 877*b121cb00SDimitry Andric if (__has_val) 878*b121cb00SDimitry Andric std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_); 879*b121cb00SDimitry Andric else 880*b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 881*b121cb00SDimitry Andric } 882*b121cb00SDimitry Andric 883bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 88406c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) 88506c3fb27SDimitry Andric = default; 88606c3fb27SDimitry Andric 88706c3fb27SDimitry Andric // the expected's destructor handles this 88806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} 88906c3fb27SDimitry Andric 89006c3fb27SDimitry Andric _ValueType __val_; 89106c3fb27SDimitry Andric _ErrorType __unex_; 89206c3fb27SDimitry Andric }; 89306c3fb27SDimitry Andric 89406c3fb27SDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union, 89506c3fb27SDimitry Andric // also guaranteed elision into a potentially-overlapping subobject is unsettled (and 89606c3fb27SDimitry Andric // it's not clear that it's implementable, given that the function is allowed to clobber 89706c3fb27SDimitry Andric // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. 89806c3fb27SDimitry Andric template <class _ValueType, class _ErrorType> 89906c3fb27SDimitry Andric requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>) 90006c3fb27SDimitry Andric union __union_t<_ValueType, _ErrorType> { 901*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default; 902*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default; 903*b121cb00SDimitry Andric 904*b121cb00SDimitry Andric template <class... _Args> 905*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args) 906*b121cb00SDimitry Andric : __val_(std::forward<_Args>(__args)...) {} 907*b121cb00SDimitry Andric 908*b121cb00SDimitry Andric template <class... _Args> 909*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 910*b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 91106c3fb27SDimitry Andric 91206c3fb27SDimitry Andric template <class _Func, class... _Args> 91306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 91406c3fb27SDimitry Andric std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) 91506c3fb27SDimitry Andric : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 91606c3fb27SDimitry Andric 91706c3fb27SDimitry Andric template <class _Func, class... _Args> 91806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 91906c3fb27SDimitry Andric std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 92006c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 92106c3fb27SDimitry Andric 922*b121cb00SDimitry Andric template <class _Union> 923*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 924*b121cb00SDimitry Andric if (__has_val) 925*b121cb00SDimitry Andric std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_); 926*b121cb00SDimitry Andric else 927*b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 928*b121cb00SDimitry Andric } 929*b121cb00SDimitry Andric 93006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 93106c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) 932bdd1243dSDimitry Andric = default; 933bdd1243dSDimitry Andric 934bdd1243dSDimitry Andric // the expected's destructor handles this 935bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 93606c3fb27SDimitry Andric requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>) 937bdd1243dSDimitry Andric {} 938bdd1243dSDimitry Andric 93906c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_; 94006c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; 94106c3fb27SDimitry Andric }; 942bdd1243dSDimitry Andric 94306c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_; 944bdd1243dSDimitry Andric bool __has_val_; 945bdd1243dSDimitry Andric }; 946bdd1243dSDimitry Andric 947bdd1243dSDimitry Andric template <class _Tp, class _Err> 948bdd1243dSDimitry Andric requires is_void_v<_Tp> 949bdd1243dSDimitry Andric class expected<_Tp, _Err> { 950bdd1243dSDimitry Andric static_assert(__valid_std_unexpected<_Err>::value, 951bdd1243dSDimitry Andric "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a " 952bdd1243dSDimitry Andric "valid argument for unexpected<E> is ill-formed"); 953bdd1243dSDimitry Andric 954bdd1243dSDimitry Andric template <class, class> 955bdd1243dSDimitry Andric friend class expected; 956bdd1243dSDimitry Andric 957bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _OtherErrQual> 958bdd1243dSDimitry Andric using __can_convert = 959bdd1243dSDimitry Andric _And< is_void<_Up>, 960bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 961bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 962bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 963bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 964bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>; 965bdd1243dSDimitry Andric 966bdd1243dSDimitry Andric public: 967bdd1243dSDimitry Andric using value_type = _Tp; 968bdd1243dSDimitry Andric using error_type = _Err; 969bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 970bdd1243dSDimitry Andric 971bdd1243dSDimitry Andric template <class _Up> 972bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 973bdd1243dSDimitry Andric 974bdd1243dSDimitry Andric // [expected.void.ctor], constructors 975bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {} 976bdd1243dSDimitry Andric 977bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 978bdd1243dSDimitry Andric 979bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 980bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) 981bdd1243dSDimitry Andric = default; 982bdd1243dSDimitry Andric 983bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) 984bdd1243dSDimitry Andric noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened 985bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>) 986*b121cb00SDimitry Andric : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {} 987bdd1243dSDimitry Andric 988bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 989bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) 990bdd1243dSDimitry Andric = default; 991bdd1243dSDimitry Andric 992bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) 993bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Err>) 994bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>) 995*b121cb00SDimitry Andric : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {} 996bdd1243dSDimitry Andric 997bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 998bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value 999bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 1000bdd1243dSDimitry Andric expected(const expected<_Up, _OtherErr>& __rhs) 1001bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 1002*b121cb00SDimitry Andric : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {} 1003bdd1243dSDimitry Andric 1004bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 1005bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _OtherErr>::value 1006bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 1007bdd1243dSDimitry Andric expected(expected<_Up, _OtherErr>&& __rhs) 1008bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 1009*b121cb00SDimitry Andric : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {} 1010bdd1243dSDimitry Andric 1011bdd1243dSDimitry Andric template <class _OtherErr> 1012bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 1013bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 1014bdd1243dSDimitry Andric expected(const unexpected<_OtherErr>& __unex) 1015bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 1016*b121cb00SDimitry Andric : __union_(std::unexpect, __unex.error()), __has_val_(false) {} 1017bdd1243dSDimitry Andric 1018bdd1243dSDimitry Andric template <class _OtherErr> 1019bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 1020bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 1021bdd1243dSDimitry Andric expected(unexpected<_OtherErr>&& __unex) 1022bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 1023*b121cb00SDimitry Andric : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {} 1024bdd1243dSDimitry Andric 1025bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {} 1026bdd1243dSDimitry Andric 1027bdd1243dSDimitry Andric template <class... _Args> 1028bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 1029bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) 1030bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened 1031*b121cb00SDimitry Andric : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {} 1032bdd1243dSDimitry Andric 1033bdd1243dSDimitry Andric template <class _Up, class... _Args> 1034bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 1035bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) 1036bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 1037*b121cb00SDimitry Andric : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {} 1038bdd1243dSDimitry Andric 103906c3fb27SDimitry Andric private: 104006c3fb27SDimitry Andric template <class _Func> 104106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f) 104206c3fb27SDimitry Andric : __has_val_(true) { 104306c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 104406c3fb27SDimitry Andric } 104506c3fb27SDimitry Andric 104606c3fb27SDimitry Andric template <class _Func, class... _Args> 104706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 104806c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 104906c3fb27SDimitry Andric : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} 105006c3fb27SDimitry Andric 105106c3fb27SDimitry Andric public: 1052bdd1243dSDimitry Andric // [expected.void.dtor], destructor 1053bdd1243dSDimitry Andric 1054bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 1055bdd1243dSDimitry Andric requires is_trivially_destructible_v<_Err> 1056bdd1243dSDimitry Andric = default; 1057bdd1243dSDimitry Andric 1058bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 1059bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Err>) 1060bdd1243dSDimitry Andric { 1061bdd1243dSDimitry Andric if (!__has_val_) { 1062bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1063bdd1243dSDimitry Andric } 1064bdd1243dSDimitry Andric } 1065bdd1243dSDimitry Andric 1066bdd1243dSDimitry Andric // [expected.void.assign], assignment 1067bdd1243dSDimitry Andric 1068bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 1069bdd1243dSDimitry Andric 1070bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) 1071bdd1243dSDimitry Andric noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened 1072bdd1243dSDimitry Andric requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>) 1073bdd1243dSDimitry Andric { 1074bdd1243dSDimitry Andric if (__has_val_) { 1075bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 1076bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); 1077bdd1243dSDimitry Andric __has_val_ = false; 1078bdd1243dSDimitry Andric } 1079bdd1243dSDimitry Andric } else { 1080bdd1243dSDimitry Andric if (__rhs.__has_val_) { 1081bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1082bdd1243dSDimitry Andric __has_val_ = true; 1083bdd1243dSDimitry Andric } else { 1084bdd1243dSDimitry Andric __union_.__unex_ = __rhs.__union_.__unex_; 1085bdd1243dSDimitry Andric } 1086bdd1243dSDimitry Andric } 1087bdd1243dSDimitry Andric return *this; 1088bdd1243dSDimitry Andric } 1089bdd1243dSDimitry Andric 1090bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete; 1091bdd1243dSDimitry Andric 1092bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) 1093bdd1243dSDimitry Andric noexcept(is_nothrow_move_assignable_v<_Err> && 1094bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>) 1095bdd1243dSDimitry Andric requires(is_move_assignable_v<_Err> && 1096bdd1243dSDimitry Andric is_move_constructible_v<_Err>) 1097bdd1243dSDimitry Andric { 1098bdd1243dSDimitry Andric if (__has_val_) { 1099bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 1100bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); 1101bdd1243dSDimitry Andric __has_val_ = false; 1102bdd1243dSDimitry Andric } 1103bdd1243dSDimitry Andric } else { 1104bdd1243dSDimitry Andric if (__rhs.__has_val_) { 1105bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1106bdd1243dSDimitry Andric __has_val_ = true; 1107bdd1243dSDimitry Andric } else { 1108bdd1243dSDimitry Andric __union_.__unex_ = std::move(__rhs.__union_.__unex_); 1109bdd1243dSDimitry Andric } 1110bdd1243dSDimitry Andric } 1111bdd1243dSDimitry Andric return *this; 1112bdd1243dSDimitry Andric } 1113bdd1243dSDimitry Andric 1114bdd1243dSDimitry Andric template <class _OtherErr> 1115bdd1243dSDimitry Andric requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>) 1116bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 1117bdd1243dSDimitry Andric if (__has_val_) { 1118bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __un.error()); 1119bdd1243dSDimitry Andric __has_val_ = false; 1120bdd1243dSDimitry Andric } else { 1121bdd1243dSDimitry Andric __union_.__unex_ = __un.error(); 1122bdd1243dSDimitry Andric } 1123bdd1243dSDimitry Andric return *this; 1124bdd1243dSDimitry Andric } 1125bdd1243dSDimitry Andric 1126bdd1243dSDimitry Andric template <class _OtherErr> 1127bdd1243dSDimitry Andric requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>) 1128bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 1129bdd1243dSDimitry Andric if (__has_val_) { 1130bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error())); 1131bdd1243dSDimitry Andric __has_val_ = false; 1132bdd1243dSDimitry Andric } else { 1133bdd1243dSDimitry Andric __union_.__unex_ = std::move(__un.error()); 1134bdd1243dSDimitry Andric } 1135bdd1243dSDimitry Andric return *this; 1136bdd1243dSDimitry Andric } 1137bdd1243dSDimitry Andric 1138bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept { 1139bdd1243dSDimitry Andric if (!__has_val_) { 1140bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1141bdd1243dSDimitry Andric __has_val_ = true; 1142bdd1243dSDimitry Andric } 1143bdd1243dSDimitry Andric } 1144bdd1243dSDimitry Andric 1145bdd1243dSDimitry Andric // [expected.void.swap], swap 1146bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) 1147bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) 1148bdd1243dSDimitry Andric requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>) 1149bdd1243dSDimitry Andric { 1150bdd1243dSDimitry Andric auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { 1151bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); 1152bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 1153bdd1243dSDimitry Andric __with_val.__has_val_ = false; 1154bdd1243dSDimitry Andric __with_err.__has_val_ = true; 1155bdd1243dSDimitry Andric }; 1156bdd1243dSDimitry Andric 1157bdd1243dSDimitry Andric if (__has_val_) { 1158bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 1159bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 1160bdd1243dSDimitry Andric } 1161bdd1243dSDimitry Andric } else { 1162bdd1243dSDimitry Andric if (__rhs.__has_val_) { 1163bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 1164bdd1243dSDimitry Andric } else { 1165bdd1243dSDimitry Andric using std::swap; 1166bdd1243dSDimitry Andric swap(__union_.__unex_, __rhs.__union_.__unex_); 1167bdd1243dSDimitry Andric } 1168bdd1243dSDimitry Andric } 1169bdd1243dSDimitry Andric } 1170bdd1243dSDimitry Andric 1171bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) 1172bdd1243dSDimitry Andric noexcept(noexcept(__x.swap(__y))) 1173bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 1174bdd1243dSDimitry Andric { 1175bdd1243dSDimitry Andric __x.swap(__y); 1176bdd1243dSDimitry Andric } 1177bdd1243dSDimitry Andric 1178bdd1243dSDimitry Andric // [expected.void.obs], observers 1179bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } 1180bdd1243dSDimitry Andric 1181bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } 1182bdd1243dSDimitry Andric 1183bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { 118406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 1185bdd1243dSDimitry Andric } 1186bdd1243dSDimitry Andric 1187bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { 1188bdd1243dSDimitry Andric if (!__has_val_) { 118906c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(__union_.__unex_); 1190bdd1243dSDimitry Andric } 1191bdd1243dSDimitry Andric } 1192bdd1243dSDimitry Andric 1193bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() && { 1194bdd1243dSDimitry Andric if (!__has_val_) { 119506c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); 1196bdd1243dSDimitry Andric } 1197bdd1243dSDimitry Andric } 1198bdd1243dSDimitry Andric 1199bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 120006c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1201bdd1243dSDimitry Andric return __union_.__unex_; 1202bdd1243dSDimitry Andric } 1203bdd1243dSDimitry Andric 1204bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 120506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1206bdd1243dSDimitry Andric return __union_.__unex_; 1207bdd1243dSDimitry Andric } 1208bdd1243dSDimitry Andric 1209bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 121006c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1211bdd1243dSDimitry Andric return std::move(__union_.__unex_); 1212bdd1243dSDimitry Andric } 1213bdd1243dSDimitry Andric 1214bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 121506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1216bdd1243dSDimitry Andric return std::move(__union_.__unex_); 1217bdd1243dSDimitry Andric } 1218bdd1243dSDimitry Andric 121906c3fb27SDimitry Andric template <class _Up = _Err> 122006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { 122106c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 122206c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 122306c3fb27SDimitry Andric if (has_value()) { 122406c3fb27SDimitry Andric return std::forward<_Up>(__error); 122506c3fb27SDimitry Andric } 122606c3fb27SDimitry Andric return error(); 122706c3fb27SDimitry Andric } 122806c3fb27SDimitry Andric 122906c3fb27SDimitry Andric template <class _Up = _Err> 123006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { 123106c3fb27SDimitry Andric static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); 123206c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 123306c3fb27SDimitry Andric if (has_value()) { 123406c3fb27SDimitry Andric return std::forward<_Up>(__error); 123506c3fb27SDimitry Andric } 123606c3fb27SDimitry Andric return std::move(error()); 123706c3fb27SDimitry Andric } 123806c3fb27SDimitry Andric 123906c3fb27SDimitry Andric // [expected.void.monadic], monadic 124006c3fb27SDimitry Andric template <class _Func> 124106c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 124206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { 124306c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 124406c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 124506c3fb27SDimitry Andric static_assert( 124606c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 124706c3fb27SDimitry Andric if (has_value()) { 124806c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 124906c3fb27SDimitry Andric } 125006c3fb27SDimitry Andric return _Up(unexpect, error()); 125106c3fb27SDimitry Andric } 125206c3fb27SDimitry Andric 125306c3fb27SDimitry Andric template <class _Func> 125406c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 125506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { 125606c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 125706c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 125806c3fb27SDimitry Andric static_assert( 125906c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 126006c3fb27SDimitry Andric if (has_value()) { 126106c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 126206c3fb27SDimitry Andric } 126306c3fb27SDimitry Andric return _Up(unexpect, error()); 126406c3fb27SDimitry Andric } 126506c3fb27SDimitry Andric 126606c3fb27SDimitry Andric template <class _Func> 126706c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 126806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { 126906c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 127006c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 127106c3fb27SDimitry Andric static_assert( 127206c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 127306c3fb27SDimitry Andric if (has_value()) { 127406c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 127506c3fb27SDimitry Andric } 127606c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 127706c3fb27SDimitry Andric } 127806c3fb27SDimitry Andric 127906c3fb27SDimitry Andric template <class _Func> 128006c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 128106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 128206c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 128306c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 128406c3fb27SDimitry Andric static_assert( 128506c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 128606c3fb27SDimitry Andric if (has_value()) { 128706c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 128806c3fb27SDimitry Andric } 128906c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 129006c3fb27SDimitry Andric } 129106c3fb27SDimitry Andric 129206c3fb27SDimitry Andric template <class _Func> 129306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { 129406c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; 129506c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 129606c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 129706c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 129806c3fb27SDimitry Andric if (has_value()) { 129906c3fb27SDimitry Andric return _Gp(); 130006c3fb27SDimitry Andric } 130106c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 130206c3fb27SDimitry Andric } 130306c3fb27SDimitry Andric 130406c3fb27SDimitry Andric template <class _Func> 130506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { 130606c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; 130706c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 130806c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 130906c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 131006c3fb27SDimitry Andric if (has_value()) { 131106c3fb27SDimitry Andric return _Gp(); 131206c3fb27SDimitry Andric } 131306c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 131406c3fb27SDimitry Andric } 131506c3fb27SDimitry Andric 131606c3fb27SDimitry Andric template <class _Func> 131706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { 131806c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; 131906c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, 132006c3fb27SDimitry Andric "The result of f(std::move(error())) must be a specialization of std::expected"); 132106c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 132206c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 132306c3fb27SDimitry Andric if (has_value()) { 132406c3fb27SDimitry Andric return _Gp(); 132506c3fb27SDimitry Andric } 132606c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 132706c3fb27SDimitry Andric } 132806c3fb27SDimitry Andric 132906c3fb27SDimitry Andric template <class _Func> 133006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { 133106c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; 133206c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, 133306c3fb27SDimitry Andric "The result of f(std::move(error())) must be a specialization of std::expected"); 133406c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 133506c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 133606c3fb27SDimitry Andric if (has_value()) { 133706c3fb27SDimitry Andric return _Gp(); 133806c3fb27SDimitry Andric } 133906c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 134006c3fb27SDimitry Andric } 134106c3fb27SDimitry Andric 134206c3fb27SDimitry Andric template <class _Func> 134306c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 134406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { 134506c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 134606c3fb27SDimitry Andric if (!has_value()) { 134706c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 134806c3fb27SDimitry Andric } 134906c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 135006c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 135106c3fb27SDimitry Andric } else { 135206c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 135306c3fb27SDimitry Andric return expected<_Up, _Err>(); 135406c3fb27SDimitry Andric } 135506c3fb27SDimitry Andric } 135606c3fb27SDimitry Andric 135706c3fb27SDimitry Andric template <class _Func> 135806c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 135906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { 136006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 136106c3fb27SDimitry Andric if (!has_value()) { 136206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 136306c3fb27SDimitry Andric } 136406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 136506c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 136606c3fb27SDimitry Andric } else { 136706c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 136806c3fb27SDimitry Andric return expected<_Up, _Err>(); 136906c3fb27SDimitry Andric } 137006c3fb27SDimitry Andric } 137106c3fb27SDimitry Andric 137206c3fb27SDimitry Andric template <class _Func> 137306c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 137406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { 137506c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 137606c3fb27SDimitry Andric if (!has_value()) { 137706c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 137806c3fb27SDimitry Andric } 137906c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 138006c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 138106c3fb27SDimitry Andric } else { 138206c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 138306c3fb27SDimitry Andric return expected<_Up, _Err>(); 138406c3fb27SDimitry Andric } 138506c3fb27SDimitry Andric } 138606c3fb27SDimitry Andric 138706c3fb27SDimitry Andric template <class _Func> 138806c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 138906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { 139006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 139106c3fb27SDimitry Andric if (!has_value()) { 139206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 139306c3fb27SDimitry Andric } 139406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 139506c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 139606c3fb27SDimitry Andric } else { 139706c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 139806c3fb27SDimitry Andric return expected<_Up, _Err>(); 139906c3fb27SDimitry Andric } 140006c3fb27SDimitry Andric } 140106c3fb27SDimitry Andric 140206c3fb27SDimitry Andric template <class _Func> 140306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { 140406c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; 140506c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 140606c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 140706c3fb27SDimitry Andric if (has_value()) { 140806c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 140906c3fb27SDimitry Andric } 141006c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 141106c3fb27SDimitry Andric } 141206c3fb27SDimitry Andric 141306c3fb27SDimitry Andric template <class _Func> 141406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { 141506c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; 141606c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 141706c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 141806c3fb27SDimitry Andric if (has_value()) { 141906c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 142006c3fb27SDimitry Andric } 142106c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 142206c3fb27SDimitry Andric } 142306c3fb27SDimitry Andric 142406c3fb27SDimitry Andric template <class _Func> 142506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { 142606c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; 142706c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 142806c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 142906c3fb27SDimitry Andric if (has_value()) { 143006c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 143106c3fb27SDimitry Andric } 143206c3fb27SDimitry Andric return expected<_Tp, _Gp>( 143306c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 143406c3fb27SDimitry Andric } 143506c3fb27SDimitry Andric 143606c3fb27SDimitry Andric template <class _Func> 143706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { 143806c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; 143906c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 144006c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 144106c3fb27SDimitry Andric if (has_value()) { 144206c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 144306c3fb27SDimitry Andric } 144406c3fb27SDimitry Andric return expected<_Tp, _Gp>( 144506c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 144606c3fb27SDimitry Andric } 144706c3fb27SDimitry Andric 1448bdd1243dSDimitry Andric // [expected.void.eq], equality operators 1449bdd1243dSDimitry Andric template <class _T2, class _E2> 1450bdd1243dSDimitry Andric requires is_void_v<_T2> 1451bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 1452bdd1243dSDimitry Andric if (__x.__has_val_ != __y.__has_val_) { 1453bdd1243dSDimitry Andric return false; 1454bdd1243dSDimitry Andric } else { 1455bdd1243dSDimitry Andric return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_); 1456bdd1243dSDimitry Andric } 1457bdd1243dSDimitry Andric } 1458bdd1243dSDimitry Andric 1459bdd1243dSDimitry Andric template <class _E2> 1460bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { 1461bdd1243dSDimitry Andric return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error()); 1462bdd1243dSDimitry Andric } 1463bdd1243dSDimitry Andric 1464bdd1243dSDimitry Andric private: 1465bdd1243dSDimitry Andric struct __empty_t {}; 146606c3fb27SDimitry Andric 146706c3fb27SDimitry Andric template <class _ErrorType> 146806c3fb27SDimitry Andric union __union_t { 1469bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} 1470bdd1243dSDimitry Andric 1471*b121cb00SDimitry Andric template <class... _Args> 1472*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 1473*b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 1474*b121cb00SDimitry Andric 147506c3fb27SDimitry Andric template <class _Func, class... _Args> 147606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 147706c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 147806c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 147906c3fb27SDimitry Andric 1480*b121cb00SDimitry Andric template <class _Union> 1481*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 1482*b121cb00SDimitry Andric if (__has_val) 1483*b121cb00SDimitry Andric std::construct_at(std::addressof(__empty_)); 1484*b121cb00SDimitry Andric else 1485*b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 1486*b121cb00SDimitry Andric } 1487*b121cb00SDimitry Andric 1488bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 148906c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ErrorType>) 149006c3fb27SDimitry Andric = default; 149106c3fb27SDimitry Andric 149206c3fb27SDimitry Andric // the expected's destructor handles this 149306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} 149406c3fb27SDimitry Andric 149506c3fb27SDimitry Andric __empty_t __empty_; 149606c3fb27SDimitry Andric _ErrorType __unex_; 149706c3fb27SDimitry Andric }; 149806c3fb27SDimitry Andric 149906c3fb27SDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union, 150006c3fb27SDimitry Andric // also guaranteed elision into a potentially-overlapping subobject is unsettled (and 150106c3fb27SDimitry Andric // it's not clear that it's implementable, given that the function is allowed to clobber 150206c3fb27SDimitry Andric // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. 150306c3fb27SDimitry Andric template <class _ErrorType> 150406c3fb27SDimitry Andric requires is_trivially_move_constructible_v<_ErrorType> 150506c3fb27SDimitry Andric union __union_t<_ErrorType> { 150606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} 150706c3fb27SDimitry Andric 1508*b121cb00SDimitry Andric template <class... _Args> 1509*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 1510*b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 1511*b121cb00SDimitry Andric 151206c3fb27SDimitry Andric template <class _Func, class... _Args> 151306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 151406c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 151506c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 151606c3fb27SDimitry Andric 1517*b121cb00SDimitry Andric template <class _Union> 1518*b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 1519*b121cb00SDimitry Andric if (__has_val) 1520*b121cb00SDimitry Andric std::construct_at(std::addressof(__empty_)); 1521*b121cb00SDimitry Andric else 1522*b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 1523*b121cb00SDimitry Andric } 1524*b121cb00SDimitry Andric 152506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 152606c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ErrorType>) 1527bdd1243dSDimitry Andric = default; 1528bdd1243dSDimitry Andric 1529bdd1243dSDimitry Andric // the expected's destructor handles this 1530bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 153106c3fb27SDimitry Andric requires(!is_trivially_destructible_v<_ErrorType>) 1532bdd1243dSDimitry Andric {} 1533bdd1243dSDimitry Andric 1534bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; 153506c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; 153606c3fb27SDimitry Andric }; 1537bdd1243dSDimitry Andric 153806c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_; 1539bdd1243dSDimitry Andric bool __has_val_; 1540bdd1243dSDimitry Andric }; 1541bdd1243dSDimitry Andric 1542bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1543bdd1243dSDimitry Andric 1544bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 23 1545bdd1243dSDimitry Andric 154606c3fb27SDimitry Andric _LIBCPP_POP_MACROS 154706c3fb27SDimitry Andric 1548bdd1243dSDimitry Andric #endif // _LIBCPP___EXPECTED_EXPECTED_H 1549