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 { 93*cb14a3feSDimitry Andric static_assert(!is_reference_v<_Tp> && !is_function_v<_Tp> && !is_same_v<remove_cv_t<_Tp>, in_place_t> && 94*cb14a3feSDimitry Andric !is_same_v<remove_cv_t<_Tp>, unexpect_t> && !__is_std_unexpected<remove_cv_t<_Tp>>::value && 95*cb14a3feSDimitry Andric __valid_std_unexpected<_Err>::value, 96bdd1243dSDimitry Andric "[expected.object.general] A program that instantiates the definition of template expected<T, E> for a " 97bdd1243dSDimitry Andric "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a " 98bdd1243dSDimitry Andric "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the " 99bdd1243dSDimitry Andric "definition of the template expected<T, E> with a type for the E parameter that is not a valid " 100bdd1243dSDimitry Andric "template argument for unexpected is ill-formed."); 101bdd1243dSDimitry Andric 102bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 103bdd1243dSDimitry Andric friend class expected; 104bdd1243dSDimitry Andric 105bdd1243dSDimitry Andric public: 106bdd1243dSDimitry Andric using value_type = _Tp; 107bdd1243dSDimitry Andric using error_type = _Err; 108bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 109bdd1243dSDimitry Andric 110bdd1243dSDimitry Andric template <class _Up> 111bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 112bdd1243dSDimitry Andric 113bdd1243dSDimitry Andric // [expected.object.ctor], constructors 114*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened 115bdd1243dSDimitry Andric requires is_default_constructible_v<_Tp> 116b121cb00SDimitry Andric : __union_(std::in_place), __has_val_(true) {} 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 119bdd1243dSDimitry Andric 120bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 121*cb14a3feSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Tp> && 122bdd1243dSDimitry Andric is_trivially_copy_constructible_v<_Err>) 123bdd1243dSDimitry Andric = default; 124bdd1243dSDimitry Andric 125*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) noexcept( 126*cb14a3feSDimitry Andric is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened 127bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && 128bdd1243dSDimitry Andric !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)) 129b121cb00SDimitry Andric : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {} 130bdd1243dSDimitry Andric 131bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 132*cb14a3feSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Tp> && 133*cb14a3feSDimitry Andric is_trivially_move_constructible_v<_Err>) 134bdd1243dSDimitry Andric = default; 135bdd1243dSDimitry Andric 136*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) noexcept( 137*cb14a3feSDimitry Andric is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) 138bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && 139bdd1243dSDimitry Andric !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)) 140b121cb00SDimitry Andric : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {} 141bdd1243dSDimitry Andric 142bdd1243dSDimitry Andric private: 143bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual> 144bdd1243dSDimitry Andric using __can_convert = 145bdd1243dSDimitry Andric _And< is_constructible<_Tp, _UfQual>, 146bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 1475f757f3fSDimitry Andric _If<_Not<is_same<remove_cv_t<_Tp>, bool>>::value, 1485f757f3fSDimitry Andric _And< _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>, 149bdd1243dSDimitry Andric _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>, 150bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>, 151bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>, 152bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>, 153bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>, 154bdd1243dSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>, 1555f757f3fSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>>, 1565f757f3fSDimitry Andric true_type>, 157bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 158bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 159bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 160bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >; 161bdd1243dSDimitry Andric 16206c3fb27SDimitry Andric template <class _Func, class... _Args> 16306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 16406c3fb27SDimitry Andric std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 16506c3fb27SDimitry Andric : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(true) {} 16606c3fb27SDimitry Andric 16706c3fb27SDimitry Andric template <class _Func, class... _Args> 16806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 16906c3fb27SDimitry Andric std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 17006c3fb27SDimitry Andric : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} 171bdd1243dSDimitry Andric 172bdd1243dSDimitry Andric public: 173bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 174bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value 175bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> || 176bdd1243dSDimitry Andric !is_convertible_v<const _OtherErr&, _Err>) 177*cb14a3feSDimitry Andric expected(const expected<_Up, _OtherErr>& __other) noexcept( 178*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, const _Up&> && 179bdd1243dSDimitry Andric is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 180b121cb00SDimitry Andric : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {} 181bdd1243dSDimitry Andric 182bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 183bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value 184bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>) 185*cb14a3feSDimitry Andric expected(expected<_Up, _OtherErr>&& __other) noexcept( 186*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 187b121cb00SDimitry Andric : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {} 188bdd1243dSDimitry Andric 189bdd1243dSDimitry Andric template <class _Up = _Tp> 190bdd1243dSDimitry Andric requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> && 1915f757f3fSDimitry Andric is_constructible_v<_Tp, _Up> && !__is_std_unexpected<remove_cvref_t<_Up>>::value && 1925f757f3fSDimitry Andric (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value)) 193bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>) 194b121cb00SDimitry Andric expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened 195b121cb00SDimitry Andric : __union_(std::in_place, std::forward<_Up>(__u)), __has_val_(true) {} 196bdd1243dSDimitry Andric 197bdd1243dSDimitry Andric template <class _OtherErr> 198bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 199*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected( 200*cb14a3feSDimitry Andric const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 201b121cb00SDimitry Andric : __union_(std::unexpect, __unex.error()), __has_val_(false) {} 202bdd1243dSDimitry Andric 203bdd1243dSDimitry Andric template <class _OtherErr> 204bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 205bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 206*cb14a3feSDimitry Andric expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 207b121cb00SDimitry Andric : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {} 208bdd1243dSDimitry Andric 209bdd1243dSDimitry Andric template <class... _Args> 210bdd1243dSDimitry Andric requires is_constructible_v<_Tp, _Args...> 211*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) noexcept( 212*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, _Args...>) // strengthened 213b121cb00SDimitry Andric : __union_(std::in_place, std::forward<_Args>(__args)...), __has_val_(true) {} 214bdd1243dSDimitry Andric 215bdd1243dSDimitry Andric template <class _Up, class... _Args> 216bdd1243dSDimitry Andric requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... > 217*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( 218*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened 219b121cb00SDimitry Andric : __union_(std::in_place, __il, std::forward<_Args>(__args)...), __has_val_(true) {} 220bdd1243dSDimitry Andric 221bdd1243dSDimitry Andric template <class... _Args> 222bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 223*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept( 224*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, _Args...>) // strengthened 225b121cb00SDimitry Andric : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {} 226bdd1243dSDimitry Andric 227bdd1243dSDimitry Andric template <class _Up, class... _Args> 228bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 229*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( 230*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 231b121cb00SDimitry Andric : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {} 232bdd1243dSDimitry Andric 233bdd1243dSDimitry Andric // [expected.object.dtor], destructor 234bdd1243dSDimitry Andric 235bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 236bdd1243dSDimitry Andric requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) 237bdd1243dSDimitry Andric = default; 238bdd1243dSDimitry Andric 239bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 240bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) 241bdd1243dSDimitry Andric { 242bdd1243dSDimitry Andric if (__has_val_) { 243bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 244bdd1243dSDimitry Andric } else { 245bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 246bdd1243dSDimitry Andric } 247bdd1243dSDimitry Andric } 248bdd1243dSDimitry Andric 249bdd1243dSDimitry Andric private: 250bdd1243dSDimitry Andric template <class _T1, class _T2, class... _Args> 251bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) { 252bdd1243dSDimitry Andric if constexpr (is_nothrow_constructible_v<_T1, _Args...>) { 253bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 254bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); 255bdd1243dSDimitry Andric } else if constexpr (is_nothrow_move_constructible_v<_T1>) { 256bdd1243dSDimitry Andric _T1 __tmp(std::forward<_Args>(__args)...); 257bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 258bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::move(__tmp)); 259bdd1243dSDimitry Andric } else { 260bdd1243dSDimitry Andric static_assert( 261bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_T2>, 262bdd1243dSDimitry Andric "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can " 263bdd1243dSDimitry Andric "be reverted to the previous state in case an exception is thrown during the assignment."); 264bdd1243dSDimitry Andric _T2 __tmp(std::move(__oldval)); 265bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 2661ac55f4cSDimitry Andric auto __trans = 2671ac55f4cSDimitry Andric std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); 268bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); 269bdd1243dSDimitry Andric __trans.__complete(); 270bdd1243dSDimitry Andric } 271bdd1243dSDimitry Andric } 272bdd1243dSDimitry Andric 273bdd1243dSDimitry Andric public: 274bdd1243dSDimitry Andric // [expected.object.assign], assignment 275bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 276bdd1243dSDimitry Andric 277*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept( 278*cb14a3feSDimitry Andric is_nothrow_copy_assignable_v<_Tp> && is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_assignable_v<_Err> && 279bdd1243dSDimitry Andric is_nothrow_copy_constructible_v<_Err>) // strengthened 280*cb14a3feSDimitry Andric requires(is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Err> && 281bdd1243dSDimitry Andric is_copy_constructible_v<_Err> && 282*cb14a3feSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) 283bdd1243dSDimitry Andric { 284bdd1243dSDimitry Andric if (__has_val_ && __rhs.__has_val_) { 285bdd1243dSDimitry Andric __union_.__val_ = __rhs.__union_.__val_; 286bdd1243dSDimitry Andric } else if (__has_val_) { 287bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_); 288bdd1243dSDimitry Andric } else if (__rhs.__has_val_) { 289bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_); 290bdd1243dSDimitry Andric } else { 291bdd1243dSDimitry Andric __union_.__unex_ = __rhs.__union_.__unex_; 292bdd1243dSDimitry Andric } 293bdd1243dSDimitry Andric // note: only reached if no exception+rollback was done inside __reinit_expected 294bdd1243dSDimitry Andric __has_val_ = __rhs.__has_val_; 295bdd1243dSDimitry Andric return *this; 296bdd1243dSDimitry Andric } 297bdd1243dSDimitry Andric 298*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& 299*cb14a3feSDimitry Andric operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Tp> && is_nothrow_move_constructible_v<_Tp> && 300*cb14a3feSDimitry Andric is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>) 301*cb14a3feSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp> && is_move_constructible_v<_Err> && 302bdd1243dSDimitry Andric is_move_assignable_v<_Err> && 303*cb14a3feSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) 304bdd1243dSDimitry Andric { 305bdd1243dSDimitry Andric if (__has_val_ && __rhs.__has_val_) { 306bdd1243dSDimitry Andric __union_.__val_ = std::move(__rhs.__union_.__val_); 307bdd1243dSDimitry Andric } else if (__has_val_) { 308bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_)); 309bdd1243dSDimitry Andric } else if (__rhs.__has_val_) { 310bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_)); 311bdd1243dSDimitry Andric } else { 312bdd1243dSDimitry Andric __union_.__unex_ = std::move(__rhs.__union_.__unex_); 313bdd1243dSDimitry Andric } 314bdd1243dSDimitry Andric // note: only reached if no exception+rollback was done inside __reinit_expected 315bdd1243dSDimitry Andric __has_val_ = __rhs.__has_val_; 316bdd1243dSDimitry Andric return *this; 317bdd1243dSDimitry Andric } 318bdd1243dSDimitry Andric 319bdd1243dSDimitry Andric template <class _Up = _Tp> 320bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v) 321*cb14a3feSDimitry Andric requires(!is_same_v<expected, remove_cvref_t<_Up>> && !__is_std_unexpected<remove_cvref_t<_Up>>::value && 322*cb14a3feSDimitry Andric is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> && 323*cb14a3feSDimitry Andric (is_nothrow_constructible_v<_Tp, _Up> || is_nothrow_move_constructible_v<_Tp> || 324bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 325bdd1243dSDimitry Andric { 326bdd1243dSDimitry Andric if (__has_val_) { 327bdd1243dSDimitry Andric __union_.__val_ = std::forward<_Up>(__v); 328bdd1243dSDimitry Andric } else { 329bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v)); 330bdd1243dSDimitry Andric __has_val_ = true; 331bdd1243dSDimitry Andric } 332bdd1243dSDimitry Andric return *this; 333bdd1243dSDimitry Andric } 334bdd1243dSDimitry Andric 335bdd1243dSDimitry Andric private: 336bdd1243dSDimitry Andric template <class _OtherErrQual> 337bdd1243dSDimitry Andric static constexpr bool __can_assign_from_unexpected = 338bdd1243dSDimitry Andric _And< is_constructible<_Err, _OtherErrQual>, 339bdd1243dSDimitry Andric is_assignable<_Err&, _OtherErrQual>, 340bdd1243dSDimitry Andric _Lazy<_Or, 341bdd1243dSDimitry Andric is_nothrow_constructible<_Err, _OtherErrQual>, 342bdd1243dSDimitry Andric is_nothrow_move_constructible<_Tp>, 343bdd1243dSDimitry Andric is_nothrow_move_constructible<_Err>> >::value; 344bdd1243dSDimitry Andric 345bdd1243dSDimitry Andric public: 346bdd1243dSDimitry Andric template <class _OtherErr> 347bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<const _OtherErr&>) 348bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 349bdd1243dSDimitry Andric if (__has_val_) { 350bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, __un.error()); 351bdd1243dSDimitry Andric __has_val_ = false; 352bdd1243dSDimitry Andric } else { 353bdd1243dSDimitry Andric __union_.__unex_ = __un.error(); 354bdd1243dSDimitry Andric } 355bdd1243dSDimitry Andric return *this; 356bdd1243dSDimitry Andric } 357bdd1243dSDimitry Andric 358bdd1243dSDimitry Andric template <class _OtherErr> 359bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<_OtherErr>) 360bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 361bdd1243dSDimitry Andric if (__has_val_) { 362bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error())); 363bdd1243dSDimitry Andric __has_val_ = false; 364bdd1243dSDimitry Andric } else { 365bdd1243dSDimitry Andric __union_.__unex_ = std::move(__un.error()); 366bdd1243dSDimitry Andric } 367bdd1243dSDimitry Andric return *this; 368bdd1243dSDimitry Andric } 369bdd1243dSDimitry Andric 370bdd1243dSDimitry Andric template <class... _Args> 371bdd1243dSDimitry Andric requires is_nothrow_constructible_v<_Tp, _Args...> 372bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept { 373bdd1243dSDimitry Andric if (__has_val_) { 374bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 375bdd1243dSDimitry Andric } else { 376bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 377bdd1243dSDimitry Andric } 378b121cb00SDimitry Andric std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...); 379b121cb00SDimitry Andric __has_val_ = true; 380b121cb00SDimitry Andric return __union_.__val_; 381bdd1243dSDimitry Andric } 382bdd1243dSDimitry Andric 383bdd1243dSDimitry Andric template <class _Up, class... _Args> 384bdd1243dSDimitry Andric requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... > 385bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept { 386bdd1243dSDimitry Andric if (__has_val_) { 387bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 388bdd1243dSDimitry Andric } else { 389bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 390bdd1243dSDimitry Andric } 391b121cb00SDimitry Andric std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...); 392b121cb00SDimitry Andric __has_val_ = true; 393b121cb00SDimitry Andric return __union_.__val_; 394bdd1243dSDimitry Andric } 395bdd1243dSDimitry Andric 396bdd1243dSDimitry Andric public: 397bdd1243dSDimitry Andric // [expected.object.swap], swap 398*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 399*cb14a3feSDimitry Andric swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp> && 400*cb14a3feSDimitry Andric is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) 401*cb14a3feSDimitry Andric requires(is_swappable_v<_Tp> && is_swappable_v<_Err> && is_move_constructible_v<_Tp> && 402bdd1243dSDimitry Andric is_move_constructible_v<_Err> && 403*cb14a3feSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) 404bdd1243dSDimitry Andric { 405bdd1243dSDimitry Andric auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { 406bdd1243dSDimitry Andric if constexpr (is_nothrow_move_constructible_v<_Err>) { 407bdd1243dSDimitry Andric _Err __tmp(std::move(__with_err.__union_.__unex_)); 408bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 4091ac55f4cSDimitry Andric auto __trans = std::__make_exception_guard([&] { 410bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp)); 411bdd1243dSDimitry Andric }); 412bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_)); 413bdd1243dSDimitry Andric __trans.__complete(); 414bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_val.__union_.__val_)); 415bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp)); 416bdd1243dSDimitry Andric } else { 417bdd1243dSDimitry Andric static_assert(is_nothrow_move_constructible_v<_Tp>, 418bdd1243dSDimitry Andric "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so " 419bdd1243dSDimitry Andric "that it can be reverted to the previous state in case an exception is thrown during swap."); 420bdd1243dSDimitry Andric _Tp __tmp(std::move(__with_val.__union_.__val_)); 421bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_val.__union_.__val_)); 4221ac55f4cSDimitry Andric auto __trans = std::__make_exception_guard([&] { 423bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); 424bdd1243dSDimitry Andric }); 425bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); 426bdd1243dSDimitry Andric __trans.__complete(); 427bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 428bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp)); 429bdd1243dSDimitry Andric } 430bdd1243dSDimitry Andric __with_val.__has_val_ = false; 431bdd1243dSDimitry Andric __with_err.__has_val_ = true; 432bdd1243dSDimitry Andric }; 433bdd1243dSDimitry Andric 434bdd1243dSDimitry Andric if (__has_val_) { 435bdd1243dSDimitry Andric if (__rhs.__has_val_) { 436bdd1243dSDimitry Andric using std::swap; 437bdd1243dSDimitry Andric swap(__union_.__val_, __rhs.__union_.__val_); 438bdd1243dSDimitry Andric } else { 439bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 440bdd1243dSDimitry Andric } 441bdd1243dSDimitry Andric } else { 442bdd1243dSDimitry Andric if (__rhs.__has_val_) { 443bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 444bdd1243dSDimitry Andric } else { 445bdd1243dSDimitry Andric using std::swap; 446bdd1243dSDimitry Andric swap(__union_.__unex_, __rhs.__union_.__unex_); 447bdd1243dSDimitry Andric } 448bdd1243dSDimitry Andric } 449bdd1243dSDimitry Andric } 450bdd1243dSDimitry Andric 451*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y))) 452bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 453bdd1243dSDimitry Andric { 454bdd1243dSDimitry Andric __x.swap(__y); 455bdd1243dSDimitry Andric } 456bdd1243dSDimitry Andric 457bdd1243dSDimitry Andric // [expected.object.obs], observers 458bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { 45906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); 460bdd1243dSDimitry Andric return std::addressof(__union_.__val_); 461bdd1243dSDimitry Andric } 462bdd1243dSDimitry Andric 463bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { 46406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); 465bdd1243dSDimitry Andric return std::addressof(__union_.__val_); 466bdd1243dSDimitry Andric } 467bdd1243dSDimitry Andric 468bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { 46906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 470bdd1243dSDimitry Andric return __union_.__val_; 471bdd1243dSDimitry Andric } 472bdd1243dSDimitry Andric 473bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { 47406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 475bdd1243dSDimitry Andric return __union_.__val_; 476bdd1243dSDimitry Andric } 477bdd1243dSDimitry Andric 478bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { 47906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 480bdd1243dSDimitry Andric return std::move(__union_.__val_); 481bdd1243dSDimitry Andric } 482bdd1243dSDimitry Andric 483bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { 48406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 485bdd1243dSDimitry Andric return std::move(__union_.__val_); 486bdd1243dSDimitry Andric } 487bdd1243dSDimitry Andric 488bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } 489bdd1243dSDimitry Andric 490bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } 491bdd1243dSDimitry Andric 492bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { 49306c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 494bdd1243dSDimitry Andric if (!__has_val_) { 49506c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::as_const(error())); 496bdd1243dSDimitry Andric } 497bdd1243dSDimitry Andric return __union_.__val_; 498bdd1243dSDimitry Andric } 499bdd1243dSDimitry Andric 500bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { 50106c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 502bdd1243dSDimitry Andric if (!__has_val_) { 50306c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::as_const(error())); 504bdd1243dSDimitry Andric } 505bdd1243dSDimitry Andric return __union_.__val_; 506bdd1243dSDimitry Andric } 507bdd1243dSDimitry Andric 508bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { 50906c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, 51006c3fb27SDimitry Andric "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); 511bdd1243dSDimitry Andric if (!__has_val_) { 51206c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(error())); 513bdd1243dSDimitry Andric } 514bdd1243dSDimitry Andric return std::move(__union_.__val_); 515bdd1243dSDimitry Andric } 516bdd1243dSDimitry Andric 517bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { 51806c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, 51906c3fb27SDimitry Andric "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); 520bdd1243dSDimitry Andric if (!__has_val_) { 52106c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(error())); 522bdd1243dSDimitry Andric } 523bdd1243dSDimitry Andric return std::move(__union_.__val_); 524bdd1243dSDimitry Andric } 525bdd1243dSDimitry Andric 526bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 52706c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 528bdd1243dSDimitry Andric return __union_.__unex_; 529bdd1243dSDimitry Andric } 530bdd1243dSDimitry Andric 531bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 53206c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 533bdd1243dSDimitry Andric return __union_.__unex_; 534bdd1243dSDimitry Andric } 535bdd1243dSDimitry Andric 536bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 53706c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 538bdd1243dSDimitry Andric return std::move(__union_.__unex_); 539bdd1243dSDimitry Andric } 540bdd1243dSDimitry Andric 541bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 54206c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 543bdd1243dSDimitry Andric return std::move(__union_.__unex_); 544bdd1243dSDimitry Andric } 545bdd1243dSDimitry Andric 546bdd1243dSDimitry Andric template <class _Up> 547bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { 548bdd1243dSDimitry Andric static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); 549bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 550bdd1243dSDimitry Andric return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v)); 551bdd1243dSDimitry Andric } 552bdd1243dSDimitry Andric 553bdd1243dSDimitry Andric template <class _Up> 554bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { 555bdd1243dSDimitry Andric static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); 556bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 557bdd1243dSDimitry Andric return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v)); 558bdd1243dSDimitry Andric } 559bdd1243dSDimitry Andric 56006c3fb27SDimitry Andric template <class _Up = _Err> 56106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { 56206c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 56306c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 56406c3fb27SDimitry Andric if (has_value()) 56506c3fb27SDimitry Andric return std::forward<_Up>(__error); 56606c3fb27SDimitry Andric return error(); 56706c3fb27SDimitry Andric } 56806c3fb27SDimitry Andric 56906c3fb27SDimitry Andric template <class _Up = _Err> 57006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { 57106c3fb27SDimitry Andric static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); 57206c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 57306c3fb27SDimitry Andric if (has_value()) 57406c3fb27SDimitry Andric return std::forward<_Up>(__error); 57506c3fb27SDimitry Andric return std::move(error()); 57606c3fb27SDimitry Andric } 57706c3fb27SDimitry Andric 57806c3fb27SDimitry Andric // [expected.void.monadic], monadic 57906c3fb27SDimitry Andric template <class _Func> 58006c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 58106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { 58206c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>; 5835f757f3fSDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected"); 58406c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 5855f757f3fSDimitry Andric "The result of f(**this) must have the same error_type as this expected"); 58606c3fb27SDimitry Andric if (has_value()) { 5875f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), __union_.__val_); 58806c3fb27SDimitry Andric } 58906c3fb27SDimitry Andric return _Up(unexpect, error()); 59006c3fb27SDimitry Andric } 59106c3fb27SDimitry Andric 59206c3fb27SDimitry Andric template <class _Func> 59306c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 59406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { 59506c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>; 5965f757f3fSDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected"); 59706c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 5985f757f3fSDimitry Andric "The result of f(**this) must have the same error_type as this expected"); 59906c3fb27SDimitry Andric if (has_value()) { 6005f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), __union_.__val_); 60106c3fb27SDimitry Andric } 60206c3fb27SDimitry Andric return _Up(unexpect, error()); 60306c3fb27SDimitry Andric } 60406c3fb27SDimitry Andric 60506c3fb27SDimitry Andric template <class _Func> 60606c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 60706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { 60806c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>; 60906c3fb27SDimitry Andric static_assert( 6105f757f3fSDimitry Andric __is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected"); 61106c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 6125f757f3fSDimitry Andric "The result of f(std::move(**this)) must have the same error_type as this expected"); 61306c3fb27SDimitry Andric if (has_value()) { 6145f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_)); 61506c3fb27SDimitry Andric } 61606c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 61706c3fb27SDimitry Andric } 61806c3fb27SDimitry Andric 61906c3fb27SDimitry Andric template <class _Func> 62006c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 62106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 62206c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>; 62306c3fb27SDimitry Andric static_assert( 6245f757f3fSDimitry Andric __is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected"); 62506c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 6265f757f3fSDimitry Andric "The result of f(std::move(**this)) must have the same error_type as this expected"); 62706c3fb27SDimitry Andric if (has_value()) { 6285f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_)); 62906c3fb27SDimitry Andric } 63006c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 63106c3fb27SDimitry Andric } 63206c3fb27SDimitry Andric 63306c3fb27SDimitry Andric template <class _Func> 63406c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&> 63506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { 63606c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; 63706c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 63806c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 63906c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 64006c3fb27SDimitry Andric if (has_value()) { 6415f757f3fSDimitry Andric return _Gp(in_place, __union_.__val_); 64206c3fb27SDimitry Andric } 64306c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 64406c3fb27SDimitry Andric } 64506c3fb27SDimitry Andric 64606c3fb27SDimitry Andric template <class _Func> 64706c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&> 64806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { 64906c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; 65006c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 65106c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 65206c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 65306c3fb27SDimitry Andric if (has_value()) { 6545f757f3fSDimitry Andric return _Gp(in_place, __union_.__val_); 65506c3fb27SDimitry Andric } 65606c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 65706c3fb27SDimitry Andric } 65806c3fb27SDimitry Andric 65906c3fb27SDimitry Andric template <class _Func> 66006c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&&> 66106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { 66206c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; 66306c3fb27SDimitry Andric static_assert( 66406c3fb27SDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 66506c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 66606c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 66706c3fb27SDimitry Andric if (has_value()) { 6685f757f3fSDimitry Andric return _Gp(in_place, std::move(__union_.__val_)); 66906c3fb27SDimitry Andric } 67006c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 67106c3fb27SDimitry Andric } 67206c3fb27SDimitry Andric 67306c3fb27SDimitry Andric template <class _Func> 67406c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&&> 67506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { 67606c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; 67706c3fb27SDimitry Andric static_assert( 67806c3fb27SDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 67906c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 68006c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 68106c3fb27SDimitry Andric if (has_value()) { 6825f757f3fSDimitry Andric return _Gp(in_place, std::move(__union_.__val_)); 68306c3fb27SDimitry Andric } 68406c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 68506c3fb27SDimitry Andric } 68606c3fb27SDimitry Andric 68706c3fb27SDimitry Andric template <class _Func> 68806c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 68906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { 69006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>; 69106c3fb27SDimitry Andric if (!has_value()) { 69206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 69306c3fb27SDimitry Andric } 69406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 695*cb14a3feSDimitry Andric return expected<_Up, _Err>( 696*cb14a3feSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __union_.__val_); 69706c3fb27SDimitry Andric } else { 6985f757f3fSDimitry Andric std::invoke(std::forward<_Func>(__f), __union_.__val_); 69906c3fb27SDimitry Andric return expected<_Up, _Err>(); 70006c3fb27SDimitry Andric } 70106c3fb27SDimitry Andric } 70206c3fb27SDimitry Andric 70306c3fb27SDimitry Andric template <class _Func> 70406c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 70506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { 70606c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>; 70706c3fb27SDimitry Andric if (!has_value()) { 70806c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 70906c3fb27SDimitry Andric } 71006c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 711*cb14a3feSDimitry Andric return expected<_Up, _Err>( 712*cb14a3feSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __union_.__val_); 71306c3fb27SDimitry Andric } else { 7145f757f3fSDimitry Andric std::invoke(std::forward<_Func>(__f), __union_.__val_); 71506c3fb27SDimitry Andric return expected<_Up, _Err>(); 71606c3fb27SDimitry Andric } 71706c3fb27SDimitry Andric } 71806c3fb27SDimitry Andric 71906c3fb27SDimitry Andric template <class _Func> 72006c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 72106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { 72206c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>; 72306c3fb27SDimitry Andric if (!has_value()) { 72406c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 72506c3fb27SDimitry Andric } 72606c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 72706c3fb27SDimitry Andric return expected<_Up, _Err>( 7285f757f3fSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__union_.__val_)); 72906c3fb27SDimitry Andric } else { 7305f757f3fSDimitry Andric std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_)); 73106c3fb27SDimitry Andric return expected<_Up, _Err>(); 73206c3fb27SDimitry Andric } 73306c3fb27SDimitry Andric } 73406c3fb27SDimitry Andric 73506c3fb27SDimitry Andric template <class _Func> 73606c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 73706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { 73806c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>; 73906c3fb27SDimitry Andric if (!has_value()) { 74006c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 74106c3fb27SDimitry Andric } 74206c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 74306c3fb27SDimitry Andric return expected<_Up, _Err>( 7445f757f3fSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__union_.__val_)); 74506c3fb27SDimitry Andric } else { 7465f757f3fSDimitry Andric std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_)); 74706c3fb27SDimitry Andric return expected<_Up, _Err>(); 74806c3fb27SDimitry Andric } 74906c3fb27SDimitry Andric } 75006c3fb27SDimitry Andric 75106c3fb27SDimitry Andric template <class _Func> 75206c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&> 75306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { 75406c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; 75506c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 75606c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 75706c3fb27SDimitry Andric if (has_value()) { 7585f757f3fSDimitry Andric return expected<_Tp, _Gp>(in_place, __union_.__val_); 75906c3fb27SDimitry Andric } 76006c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 76106c3fb27SDimitry Andric } 76206c3fb27SDimitry Andric 76306c3fb27SDimitry Andric template <class _Func> 76406c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&> 76506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { 76606c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; 76706c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 76806c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 76906c3fb27SDimitry Andric if (has_value()) { 7705f757f3fSDimitry Andric return expected<_Tp, _Gp>(in_place, __union_.__val_); 77106c3fb27SDimitry Andric } 77206c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 77306c3fb27SDimitry Andric } 77406c3fb27SDimitry Andric 77506c3fb27SDimitry Andric template <class _Func> 77606c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&&> 77706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { 77806c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; 77906c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 78006c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 78106c3fb27SDimitry Andric if (has_value()) { 7825f757f3fSDimitry Andric return expected<_Tp, _Gp>(in_place, std::move(__union_.__val_)); 78306c3fb27SDimitry Andric } 78406c3fb27SDimitry Andric return expected<_Tp, _Gp>( 78506c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 78606c3fb27SDimitry Andric } 78706c3fb27SDimitry Andric 78806c3fb27SDimitry Andric template <class _Func> 78906c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&&> 79006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { 79106c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; 79206c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 79306c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 79406c3fb27SDimitry Andric if (has_value()) { 7955f757f3fSDimitry Andric return expected<_Tp, _Gp>(in_place, std::move(__union_.__val_)); 79606c3fb27SDimitry Andric } 79706c3fb27SDimitry Andric return expected<_Tp, _Gp>( 79806c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 79906c3fb27SDimitry Andric } 80006c3fb27SDimitry Andric 801bdd1243dSDimitry Andric // [expected.object.eq], equality operators 802bdd1243dSDimitry Andric template <class _T2, class _E2> 803bdd1243dSDimitry Andric requires(!is_void_v<_T2>) 804bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 805bdd1243dSDimitry Andric if (__x.__has_val_ != __y.__has_val_) { 806bdd1243dSDimitry Andric return false; 807bdd1243dSDimitry Andric } else { 808bdd1243dSDimitry Andric if (__x.__has_val_) { 809bdd1243dSDimitry Andric return __x.__union_.__val_ == __y.__union_.__val_; 810bdd1243dSDimitry Andric } else { 811bdd1243dSDimitry Andric return __x.__union_.__unex_ == __y.__union_.__unex_; 812bdd1243dSDimitry Andric } 813bdd1243dSDimitry Andric } 814bdd1243dSDimitry Andric } 815bdd1243dSDimitry Andric 816bdd1243dSDimitry Andric template <class _T2> 817bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { 818bdd1243dSDimitry Andric return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v); 819bdd1243dSDimitry Andric } 820bdd1243dSDimitry Andric 821bdd1243dSDimitry Andric template <class _E2> 822bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { 823bdd1243dSDimitry Andric return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error()); 824bdd1243dSDimitry Andric } 825bdd1243dSDimitry Andric 826bdd1243dSDimitry Andric private: 82706c3fb27SDimitry Andric template <class _ValueType, class _ErrorType> 82806c3fb27SDimitry Andric union __union_t { 829b121cb00SDimitry Andric template <class... _Args> 830b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args) 831b121cb00SDimitry Andric : __val_(std::forward<_Args>(__args)...) {} 832b121cb00SDimitry Andric 833b121cb00SDimitry Andric template <class... _Args> 834b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 835b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 83606c3fb27SDimitry Andric 83706c3fb27SDimitry Andric template <class _Func, class... _Args> 83806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 83906c3fb27SDimitry Andric std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) 84006c3fb27SDimitry Andric : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 84106c3fb27SDimitry Andric 84206c3fb27SDimitry Andric template <class _Func, class... _Args> 84306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 84406c3fb27SDimitry Andric std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 84506c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 846bdd1243dSDimitry Andric 847b121cb00SDimitry Andric template <class _Union> 848b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 849b121cb00SDimitry Andric if (__has_val) 850b121cb00SDimitry Andric std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_); 851b121cb00SDimitry Andric else 852b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 853b121cb00SDimitry Andric } 854b121cb00SDimitry Andric 855bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 85606c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) 85706c3fb27SDimitry Andric = default; 85806c3fb27SDimitry Andric 85906c3fb27SDimitry Andric // the expected's destructor handles this 86006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} 86106c3fb27SDimitry Andric 86206c3fb27SDimitry Andric _ValueType __val_; 86306c3fb27SDimitry Andric _ErrorType __unex_; 86406c3fb27SDimitry Andric }; 86506c3fb27SDimitry Andric 86606c3fb27SDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union, 86706c3fb27SDimitry Andric // also guaranteed elision into a potentially-overlapping subobject is unsettled (and 86806c3fb27SDimitry Andric // it's not clear that it's implementable, given that the function is allowed to clobber 86906c3fb27SDimitry Andric // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. 87006c3fb27SDimitry Andric template <class _ValueType, class _ErrorType> 87106c3fb27SDimitry Andric requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>) 87206c3fb27SDimitry Andric union __union_t<_ValueType, _ErrorType> { 873b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default; 874b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default; 875b121cb00SDimitry Andric 876b121cb00SDimitry Andric template <class... _Args> 877b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args) 878b121cb00SDimitry Andric : __val_(std::forward<_Args>(__args)...) {} 879b121cb00SDimitry Andric 880b121cb00SDimitry Andric template <class... _Args> 881b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 882b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 88306c3fb27SDimitry Andric 88406c3fb27SDimitry Andric template <class _Func, class... _Args> 88506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 88606c3fb27SDimitry Andric std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) 88706c3fb27SDimitry Andric : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 88806c3fb27SDimitry Andric 88906c3fb27SDimitry Andric template <class _Func, class... _Args> 89006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 89106c3fb27SDimitry Andric std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 89206c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 89306c3fb27SDimitry Andric 894b121cb00SDimitry Andric template <class _Union> 895b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 896b121cb00SDimitry Andric if (__has_val) 897b121cb00SDimitry Andric std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_); 898b121cb00SDimitry Andric else 899b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 900b121cb00SDimitry Andric } 901b121cb00SDimitry Andric 90206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 90306c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) 904bdd1243dSDimitry Andric = default; 905bdd1243dSDimitry Andric 906bdd1243dSDimitry Andric // the expected's destructor handles this 907bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 90806c3fb27SDimitry Andric requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>) 909bdd1243dSDimitry Andric {} 910bdd1243dSDimitry Andric 91106c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_; 91206c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; 91306c3fb27SDimitry Andric }; 914bdd1243dSDimitry Andric 91506c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_; 916bdd1243dSDimitry Andric bool __has_val_; 917bdd1243dSDimitry Andric }; 918bdd1243dSDimitry Andric 919bdd1243dSDimitry Andric template <class _Tp, class _Err> 920bdd1243dSDimitry Andric requires is_void_v<_Tp> 921bdd1243dSDimitry Andric class expected<_Tp, _Err> { 922bdd1243dSDimitry Andric static_assert(__valid_std_unexpected<_Err>::value, 923bdd1243dSDimitry Andric "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a " 924bdd1243dSDimitry Andric "valid argument for unexpected<E> is ill-formed"); 925bdd1243dSDimitry Andric 926bdd1243dSDimitry Andric template <class, class> 927bdd1243dSDimitry Andric friend class expected; 928bdd1243dSDimitry Andric 929bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _OtherErrQual> 930bdd1243dSDimitry Andric using __can_convert = 931bdd1243dSDimitry Andric _And< is_void<_Up>, 932bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 933bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 934bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 935bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 936bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>; 937bdd1243dSDimitry Andric 938bdd1243dSDimitry Andric public: 939bdd1243dSDimitry Andric using value_type = _Tp; 940bdd1243dSDimitry Andric using error_type = _Err; 941bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 942bdd1243dSDimitry Andric 943bdd1243dSDimitry Andric template <class _Up> 944bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 945bdd1243dSDimitry Andric 946bdd1243dSDimitry Andric // [expected.void.ctor], constructors 947bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {} 948bdd1243dSDimitry Andric 949bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 950bdd1243dSDimitry Andric 951bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 952bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) 953bdd1243dSDimitry Andric = default; 954bdd1243dSDimitry Andric 955*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) noexcept( 956*cb14a3feSDimitry Andric is_nothrow_copy_constructible_v<_Err>) // strengthened 957bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>) 958b121cb00SDimitry Andric : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {} 959bdd1243dSDimitry Andric 960bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 961bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) 962bdd1243dSDimitry Andric = default; 963bdd1243dSDimitry Andric 964*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) noexcept(is_nothrow_move_constructible_v<_Err>) 965bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>) 966b121cb00SDimitry Andric : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {} 967bdd1243dSDimitry Andric 968bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 969bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value 970bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 971*cb14a3feSDimitry Andric expected(const expected<_Up, _OtherErr>& __rhs) noexcept( 972*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 973b121cb00SDimitry Andric : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {} 974bdd1243dSDimitry Andric 975bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 976bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _OtherErr>::value 977bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 978*cb14a3feSDimitry Andric expected(expected<_Up, _OtherErr>&& __rhs) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 979b121cb00SDimitry Andric : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {} 980bdd1243dSDimitry Andric 981bdd1243dSDimitry Andric template <class _OtherErr> 982bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 983*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected( 984*cb14a3feSDimitry Andric const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 985b121cb00SDimitry Andric : __union_(std::unexpect, __unex.error()), __has_val_(false) {} 986bdd1243dSDimitry Andric 987bdd1243dSDimitry Andric template <class _OtherErr> 988bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 989bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 990*cb14a3feSDimitry Andric expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 991b121cb00SDimitry Andric : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {} 992bdd1243dSDimitry Andric 993bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {} 994bdd1243dSDimitry Andric 995bdd1243dSDimitry Andric template <class... _Args> 996bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 997*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept( 998*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, _Args...>) // strengthened 999b121cb00SDimitry Andric : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {} 1000bdd1243dSDimitry Andric 1001bdd1243dSDimitry Andric template <class _Up, class... _Args> 1002bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 1003*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( 1004*cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 1005b121cb00SDimitry Andric : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {} 1006bdd1243dSDimitry Andric 100706c3fb27SDimitry Andric private: 100806c3fb27SDimitry Andric template <class _Func> 100906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f) 101006c3fb27SDimitry Andric : __has_val_(true) { 101106c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 101206c3fb27SDimitry Andric } 101306c3fb27SDimitry Andric 101406c3fb27SDimitry Andric template <class _Func, class... _Args> 101506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 101606c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 101706c3fb27SDimitry Andric : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} 101806c3fb27SDimitry Andric 101906c3fb27SDimitry Andric public: 1020bdd1243dSDimitry Andric // [expected.void.dtor], destructor 1021bdd1243dSDimitry Andric 1022bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 1023bdd1243dSDimitry Andric requires is_trivially_destructible_v<_Err> 1024bdd1243dSDimitry Andric = default; 1025bdd1243dSDimitry Andric 1026bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 1027bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Err>) 1028bdd1243dSDimitry Andric { 1029bdd1243dSDimitry Andric if (!__has_val_) { 1030bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1031bdd1243dSDimitry Andric } 1032bdd1243dSDimitry Andric } 1033bdd1243dSDimitry Andric 1034bdd1243dSDimitry Andric // [expected.void.assign], assignment 1035bdd1243dSDimitry Andric 1036bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 1037bdd1243dSDimitry Andric 1038*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept( 1039*cb14a3feSDimitry Andric is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened 1040bdd1243dSDimitry Andric requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>) 1041bdd1243dSDimitry Andric { 1042bdd1243dSDimitry Andric if (__has_val_) { 1043bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 1044bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); 1045bdd1243dSDimitry Andric __has_val_ = false; 1046bdd1243dSDimitry Andric } 1047bdd1243dSDimitry Andric } else { 1048bdd1243dSDimitry Andric if (__rhs.__has_val_) { 1049bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1050bdd1243dSDimitry Andric __has_val_ = true; 1051bdd1243dSDimitry Andric } else { 1052bdd1243dSDimitry Andric __union_.__unex_ = __rhs.__union_.__unex_; 1053bdd1243dSDimitry Andric } 1054bdd1243dSDimitry Andric } 1055bdd1243dSDimitry Andric return *this; 1056bdd1243dSDimitry Andric } 1057bdd1243dSDimitry Andric 1058bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete; 1059bdd1243dSDimitry Andric 1060*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& 1061*cb14a3feSDimitry Andric operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>) 1062*cb14a3feSDimitry Andric requires(is_move_assignable_v<_Err> && is_move_constructible_v<_Err>) 1063bdd1243dSDimitry Andric { 1064bdd1243dSDimitry Andric if (__has_val_) { 1065bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 1066bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); 1067bdd1243dSDimitry Andric __has_val_ = false; 1068bdd1243dSDimitry Andric } 1069bdd1243dSDimitry Andric } else { 1070bdd1243dSDimitry Andric if (__rhs.__has_val_) { 1071bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1072bdd1243dSDimitry Andric __has_val_ = true; 1073bdd1243dSDimitry Andric } else { 1074bdd1243dSDimitry Andric __union_.__unex_ = std::move(__rhs.__union_.__unex_); 1075bdd1243dSDimitry Andric } 1076bdd1243dSDimitry Andric } 1077bdd1243dSDimitry Andric return *this; 1078bdd1243dSDimitry Andric } 1079bdd1243dSDimitry Andric 1080bdd1243dSDimitry Andric template <class _OtherErr> 1081bdd1243dSDimitry Andric requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>) 1082bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 1083bdd1243dSDimitry Andric if (__has_val_) { 1084bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __un.error()); 1085bdd1243dSDimitry Andric __has_val_ = false; 1086bdd1243dSDimitry Andric } else { 1087bdd1243dSDimitry Andric __union_.__unex_ = __un.error(); 1088bdd1243dSDimitry Andric } 1089bdd1243dSDimitry Andric return *this; 1090bdd1243dSDimitry Andric } 1091bdd1243dSDimitry Andric 1092bdd1243dSDimitry Andric template <class _OtherErr> 1093bdd1243dSDimitry Andric requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>) 1094bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 1095bdd1243dSDimitry Andric if (__has_val_) { 1096bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error())); 1097bdd1243dSDimitry Andric __has_val_ = false; 1098bdd1243dSDimitry Andric } else { 1099bdd1243dSDimitry Andric __union_.__unex_ = std::move(__un.error()); 1100bdd1243dSDimitry Andric } 1101bdd1243dSDimitry Andric return *this; 1102bdd1243dSDimitry Andric } 1103bdd1243dSDimitry Andric 1104bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept { 1105bdd1243dSDimitry Andric if (!__has_val_) { 1106bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 1107bdd1243dSDimitry Andric __has_val_ = true; 1108bdd1243dSDimitry Andric } 1109bdd1243dSDimitry Andric } 1110bdd1243dSDimitry Andric 1111bdd1243dSDimitry Andric // [expected.void.swap], swap 1112*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 1113*cb14a3feSDimitry Andric swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) 1114bdd1243dSDimitry Andric requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>) 1115bdd1243dSDimitry Andric { 1116bdd1243dSDimitry Andric auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { 1117bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); 1118bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 1119bdd1243dSDimitry Andric __with_val.__has_val_ = false; 1120bdd1243dSDimitry Andric __with_err.__has_val_ = true; 1121bdd1243dSDimitry Andric }; 1122bdd1243dSDimitry Andric 1123bdd1243dSDimitry Andric if (__has_val_) { 1124bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 1125bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 1126bdd1243dSDimitry Andric } 1127bdd1243dSDimitry Andric } else { 1128bdd1243dSDimitry Andric if (__rhs.__has_val_) { 1129bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 1130bdd1243dSDimitry Andric } else { 1131bdd1243dSDimitry Andric using std::swap; 1132bdd1243dSDimitry Andric swap(__union_.__unex_, __rhs.__union_.__unex_); 1133bdd1243dSDimitry Andric } 1134bdd1243dSDimitry Andric } 1135bdd1243dSDimitry Andric } 1136bdd1243dSDimitry Andric 1137*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y))) 1138bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 1139bdd1243dSDimitry Andric { 1140bdd1243dSDimitry Andric __x.swap(__y); 1141bdd1243dSDimitry Andric } 1142bdd1243dSDimitry Andric 1143bdd1243dSDimitry Andric // [expected.void.obs], observers 1144bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } 1145bdd1243dSDimitry Andric 1146bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } 1147bdd1243dSDimitry Andric 1148bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { 114906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); 1150bdd1243dSDimitry Andric } 1151bdd1243dSDimitry Andric 1152bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { 1153bdd1243dSDimitry Andric if (!__has_val_) { 115406c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(__union_.__unex_); 1155bdd1243dSDimitry Andric } 1156bdd1243dSDimitry Andric } 1157bdd1243dSDimitry Andric 1158bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() && { 1159bdd1243dSDimitry Andric if (!__has_val_) { 116006c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); 1161bdd1243dSDimitry Andric } 1162bdd1243dSDimitry Andric } 1163bdd1243dSDimitry Andric 1164bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 116506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1166bdd1243dSDimitry Andric return __union_.__unex_; 1167bdd1243dSDimitry Andric } 1168bdd1243dSDimitry Andric 1169bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 117006c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1171bdd1243dSDimitry Andric return __union_.__unex_; 1172bdd1243dSDimitry Andric } 1173bdd1243dSDimitry Andric 1174bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 117506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1176bdd1243dSDimitry Andric return std::move(__union_.__unex_); 1177bdd1243dSDimitry Andric } 1178bdd1243dSDimitry Andric 1179bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 118006c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); 1181bdd1243dSDimitry Andric return std::move(__union_.__unex_); 1182bdd1243dSDimitry Andric } 1183bdd1243dSDimitry Andric 118406c3fb27SDimitry Andric template <class _Up = _Err> 118506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { 118606c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 118706c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 118806c3fb27SDimitry Andric if (has_value()) { 118906c3fb27SDimitry Andric return std::forward<_Up>(__error); 119006c3fb27SDimitry Andric } 119106c3fb27SDimitry Andric return error(); 119206c3fb27SDimitry Andric } 119306c3fb27SDimitry Andric 119406c3fb27SDimitry Andric template <class _Up = _Err> 119506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { 119606c3fb27SDimitry Andric static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); 119706c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 119806c3fb27SDimitry Andric if (has_value()) { 119906c3fb27SDimitry Andric return std::forward<_Up>(__error); 120006c3fb27SDimitry Andric } 120106c3fb27SDimitry Andric return std::move(error()); 120206c3fb27SDimitry Andric } 120306c3fb27SDimitry Andric 120406c3fb27SDimitry Andric // [expected.void.monadic], monadic 120506c3fb27SDimitry Andric template <class _Func> 120606c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 120706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { 120806c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 120906c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 121006c3fb27SDimitry Andric static_assert( 121106c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 121206c3fb27SDimitry Andric if (has_value()) { 121306c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 121406c3fb27SDimitry Andric } 121506c3fb27SDimitry Andric return _Up(unexpect, error()); 121606c3fb27SDimitry Andric } 121706c3fb27SDimitry Andric 121806c3fb27SDimitry Andric template <class _Func> 121906c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 122006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { 122106c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 122206c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 122306c3fb27SDimitry Andric static_assert( 122406c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 122506c3fb27SDimitry Andric if (has_value()) { 122606c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 122706c3fb27SDimitry Andric } 122806c3fb27SDimitry Andric return _Up(unexpect, error()); 122906c3fb27SDimitry Andric } 123006c3fb27SDimitry Andric 123106c3fb27SDimitry Andric template <class _Func> 123206c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 123306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { 123406c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 123506c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 123606c3fb27SDimitry Andric static_assert( 123706c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 123806c3fb27SDimitry Andric if (has_value()) { 123906c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 124006c3fb27SDimitry Andric } 124106c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 124206c3fb27SDimitry Andric } 124306c3fb27SDimitry Andric 124406c3fb27SDimitry Andric template <class _Func> 124506c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 124606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 124706c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 124806c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 124906c3fb27SDimitry Andric static_assert( 125006c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 125106c3fb27SDimitry Andric if (has_value()) { 125206c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 125306c3fb27SDimitry Andric } 125406c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 125506c3fb27SDimitry Andric } 125606c3fb27SDimitry Andric 125706c3fb27SDimitry Andric template <class _Func> 125806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { 125906c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; 126006c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 126106c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 126206c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 126306c3fb27SDimitry Andric if (has_value()) { 126406c3fb27SDimitry Andric return _Gp(); 126506c3fb27SDimitry Andric } 126606c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 126706c3fb27SDimitry Andric } 126806c3fb27SDimitry Andric 126906c3fb27SDimitry Andric template <class _Func> 127006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { 127106c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; 127206c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 127306c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 127406c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 127506c3fb27SDimitry Andric if (has_value()) { 127606c3fb27SDimitry Andric return _Gp(); 127706c3fb27SDimitry Andric } 127806c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 127906c3fb27SDimitry Andric } 128006c3fb27SDimitry Andric 128106c3fb27SDimitry Andric template <class _Func> 128206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { 128306c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; 1284*cb14a3feSDimitry Andric static_assert( 1285*cb14a3feSDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 128606c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 128706c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 128806c3fb27SDimitry Andric if (has_value()) { 128906c3fb27SDimitry Andric return _Gp(); 129006c3fb27SDimitry Andric } 129106c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 129206c3fb27SDimitry Andric } 129306c3fb27SDimitry Andric 129406c3fb27SDimitry Andric template <class _Func> 129506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { 129606c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; 1297*cb14a3feSDimitry Andric static_assert( 1298*cb14a3feSDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 129906c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 130006c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 130106c3fb27SDimitry Andric if (has_value()) { 130206c3fb27SDimitry Andric return _Gp(); 130306c3fb27SDimitry Andric } 130406c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 130506c3fb27SDimitry Andric } 130606c3fb27SDimitry Andric 130706c3fb27SDimitry Andric template <class _Func> 130806c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 130906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { 131006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 131106c3fb27SDimitry Andric if (!has_value()) { 131206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 131306c3fb27SDimitry Andric } 131406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 131506c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 131606c3fb27SDimitry Andric } else { 131706c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 131806c3fb27SDimitry Andric return expected<_Up, _Err>(); 131906c3fb27SDimitry Andric } 132006c3fb27SDimitry Andric } 132106c3fb27SDimitry Andric 132206c3fb27SDimitry Andric template <class _Func> 132306c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 132406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { 132506c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 132606c3fb27SDimitry Andric if (!has_value()) { 132706c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 132806c3fb27SDimitry Andric } 132906c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 133006c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 133106c3fb27SDimitry Andric } else { 133206c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 133306c3fb27SDimitry Andric return expected<_Up, _Err>(); 133406c3fb27SDimitry Andric } 133506c3fb27SDimitry Andric } 133606c3fb27SDimitry Andric 133706c3fb27SDimitry Andric template <class _Func> 133806c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 133906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { 134006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 134106c3fb27SDimitry Andric if (!has_value()) { 134206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 134306c3fb27SDimitry Andric } 134406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 134506c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 134606c3fb27SDimitry Andric } else { 134706c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 134806c3fb27SDimitry Andric return expected<_Up, _Err>(); 134906c3fb27SDimitry Andric } 135006c3fb27SDimitry Andric } 135106c3fb27SDimitry Andric 135206c3fb27SDimitry Andric template <class _Func> 135306c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 135406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { 135506c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 135606c3fb27SDimitry Andric if (!has_value()) { 135706c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 135806c3fb27SDimitry Andric } 135906c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 136006c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 136106c3fb27SDimitry Andric } else { 136206c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 136306c3fb27SDimitry Andric return expected<_Up, _Err>(); 136406c3fb27SDimitry Andric } 136506c3fb27SDimitry Andric } 136606c3fb27SDimitry Andric 136706c3fb27SDimitry Andric template <class _Func> 136806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { 136906c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; 137006c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 137106c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 137206c3fb27SDimitry Andric if (has_value()) { 137306c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 137406c3fb27SDimitry Andric } 137506c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 137606c3fb27SDimitry Andric } 137706c3fb27SDimitry Andric 137806c3fb27SDimitry Andric template <class _Func> 137906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { 138006c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; 138106c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 138206c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 138306c3fb27SDimitry Andric if (has_value()) { 138406c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 138506c3fb27SDimitry Andric } 138606c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 138706c3fb27SDimitry Andric } 138806c3fb27SDimitry Andric 138906c3fb27SDimitry Andric template <class _Func> 139006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { 139106c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; 139206c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 139306c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 139406c3fb27SDimitry Andric if (has_value()) { 139506c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 139606c3fb27SDimitry Andric } 139706c3fb27SDimitry Andric return expected<_Tp, _Gp>( 139806c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 139906c3fb27SDimitry Andric } 140006c3fb27SDimitry Andric 140106c3fb27SDimitry Andric template <class _Func> 140206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { 140306c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; 140406c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 140506c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 140606c3fb27SDimitry Andric if (has_value()) { 140706c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 140806c3fb27SDimitry Andric } 140906c3fb27SDimitry Andric return expected<_Tp, _Gp>( 141006c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 141106c3fb27SDimitry Andric } 141206c3fb27SDimitry Andric 1413bdd1243dSDimitry Andric // [expected.void.eq], equality operators 1414bdd1243dSDimitry Andric template <class _T2, class _E2> 1415bdd1243dSDimitry Andric requires is_void_v<_T2> 1416bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 1417bdd1243dSDimitry Andric if (__x.__has_val_ != __y.__has_val_) { 1418bdd1243dSDimitry Andric return false; 1419bdd1243dSDimitry Andric } else { 1420bdd1243dSDimitry Andric return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_); 1421bdd1243dSDimitry Andric } 1422bdd1243dSDimitry Andric } 1423bdd1243dSDimitry Andric 1424bdd1243dSDimitry Andric template <class _E2> 1425bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { 1426bdd1243dSDimitry Andric return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error()); 1427bdd1243dSDimitry Andric } 1428bdd1243dSDimitry Andric 1429bdd1243dSDimitry Andric private: 1430bdd1243dSDimitry Andric struct __empty_t {}; 143106c3fb27SDimitry Andric 143206c3fb27SDimitry Andric template <class _ErrorType> 143306c3fb27SDimitry Andric union __union_t { 1434bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} 1435bdd1243dSDimitry Andric 1436b121cb00SDimitry Andric template <class... _Args> 1437b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 1438b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 1439b121cb00SDimitry Andric 144006c3fb27SDimitry Andric template <class _Func, class... _Args> 144106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 144206c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 144306c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 144406c3fb27SDimitry Andric 1445b121cb00SDimitry Andric template <class _Union> 1446b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 1447b121cb00SDimitry Andric if (__has_val) 1448b121cb00SDimitry Andric std::construct_at(std::addressof(__empty_)); 1449b121cb00SDimitry Andric else 1450b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 1451b121cb00SDimitry Andric } 1452b121cb00SDimitry Andric 1453bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 145406c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ErrorType>) 145506c3fb27SDimitry Andric = default; 145606c3fb27SDimitry Andric 145706c3fb27SDimitry Andric // the expected's destructor handles this 145806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} 145906c3fb27SDimitry Andric 146006c3fb27SDimitry Andric __empty_t __empty_; 146106c3fb27SDimitry Andric _ErrorType __unex_; 146206c3fb27SDimitry Andric }; 146306c3fb27SDimitry Andric 146406c3fb27SDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union, 146506c3fb27SDimitry Andric // also guaranteed elision into a potentially-overlapping subobject is unsettled (and 146606c3fb27SDimitry Andric // it's not clear that it's implementable, given that the function is allowed to clobber 146706c3fb27SDimitry Andric // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. 146806c3fb27SDimitry Andric template <class _ErrorType> 146906c3fb27SDimitry Andric requires is_trivially_move_constructible_v<_ErrorType> 147006c3fb27SDimitry Andric union __union_t<_ErrorType> { 147106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} 14725f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default; 14735f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default; 147406c3fb27SDimitry Andric 1475b121cb00SDimitry Andric template <class... _Args> 1476b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) 1477b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 1478b121cb00SDimitry Andric 147906c3fb27SDimitry Andric template <class _Func, class... _Args> 148006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 148106c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 148206c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 148306c3fb27SDimitry Andric 1484b121cb00SDimitry Andric template <class _Union> 1485b121cb00SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { 1486b121cb00SDimitry Andric if (__has_val) 1487b121cb00SDimitry Andric std::construct_at(std::addressof(__empty_)); 1488b121cb00SDimitry Andric else 1489b121cb00SDimitry Andric std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); 1490b121cb00SDimitry Andric } 1491b121cb00SDimitry Andric 149206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 149306c3fb27SDimitry Andric requires(is_trivially_destructible_v<_ErrorType>) 1494bdd1243dSDimitry Andric = default; 1495bdd1243dSDimitry Andric 1496bdd1243dSDimitry Andric // the expected's destructor handles this 1497bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 149806c3fb27SDimitry Andric requires(!is_trivially_destructible_v<_ErrorType>) 1499bdd1243dSDimitry Andric {} 1500bdd1243dSDimitry Andric 1501bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; 150206c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; 150306c3fb27SDimitry Andric }; 1504bdd1243dSDimitry Andric 150506c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_; 1506bdd1243dSDimitry Andric bool __has_val_; 1507bdd1243dSDimitry Andric }; 1508bdd1243dSDimitry Andric 1509bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1510bdd1243dSDimitry Andric 1511bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 23 1512bdd1243dSDimitry Andric 151306c3fb27SDimitry Andric _LIBCPP_POP_MACROS 151406c3fb27SDimitry Andric 1515bdd1243dSDimitry Andric #endif // _LIBCPP___EXPECTED_EXPECTED_H 1516