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> 17bdd1243dSDimitry Andric #include <__memory/addressof.h> 18bdd1243dSDimitry Andric #include <__memory/construct_at.h> 19bdd1243dSDimitry Andric #include <__type_traits/conjunction.h> 20bdd1243dSDimitry Andric #include <__type_traits/disjunction.h> 21bdd1243dSDimitry Andric #include <__type_traits/is_assignable.h> 22bdd1243dSDimitry Andric #include <__type_traits/is_constructible.h> 23bdd1243dSDimitry Andric #include <__type_traits/is_convertible.h> 24bdd1243dSDimitry Andric #include <__type_traits/is_copy_assignable.h> 25bdd1243dSDimitry Andric #include <__type_traits/is_copy_constructible.h> 26bdd1243dSDimitry Andric #include <__type_traits/is_default_constructible.h> 27bdd1243dSDimitry Andric #include <__type_traits/is_function.h> 28bdd1243dSDimitry Andric #include <__type_traits/is_move_assignable.h> 29bdd1243dSDimitry Andric #include <__type_traits/is_move_constructible.h> 30bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h> 31bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_assignable.h> 32bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_constructible.h> 33bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_default_constructible.h> 34bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_assignable.h> 35bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_constructible.h> 36bdd1243dSDimitry Andric #include <__type_traits/is_reference.h> 37bdd1243dSDimitry Andric #include <__type_traits/is_same.h> 38bdd1243dSDimitry Andric #include <__type_traits/is_swappable.h> 39bdd1243dSDimitry Andric #include <__type_traits/is_trivially_copy_constructible.h> 40bdd1243dSDimitry Andric #include <__type_traits/is_trivially_destructible.h> 41bdd1243dSDimitry Andric #include <__type_traits/is_trivially_move_constructible.h> 42bdd1243dSDimitry Andric #include <__type_traits/is_void.h> 43bdd1243dSDimitry Andric #include <__type_traits/lazy.h> 44bdd1243dSDimitry Andric #include <__type_traits/negation.h> 45bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h> 46bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h> 47bdd1243dSDimitry Andric #include <__utility/exception_guard.h> 48bdd1243dSDimitry Andric #include <__utility/forward.h> 49bdd1243dSDimitry Andric #include <__utility/in_place.h> 50bdd1243dSDimitry Andric #include <__utility/move.h> 51bdd1243dSDimitry Andric #include <__utility/swap.h> 52bdd1243dSDimitry Andric #include <cstdlib> // for std::abort 53bdd1243dSDimitry Andric #include <initializer_list> 54bdd1243dSDimitry Andric 55bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 56bdd1243dSDimitry Andric # pragma GCC system_header 57bdd1243dSDimitry Andric #endif 58bdd1243dSDimitry Andric 59bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 23 60bdd1243dSDimitry Andric 61bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 62bdd1243dSDimitry Andric 63bdd1243dSDimitry Andric namespace __expected { 64bdd1243dSDimitry Andric 65bdd1243dSDimitry Andric template <class _Err, class _Arg> 66bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) { 67bdd1243dSDimitry Andric # ifndef _LIBCPP_NO_EXCEPTIONS 68bdd1243dSDimitry Andric throw bad_expected_access<_Err>(std::forward<_Arg>(__arg)); 69bdd1243dSDimitry Andric # else 70bdd1243dSDimitry Andric (void)__arg; 71bdd1243dSDimitry Andric std::abort(); 72bdd1243dSDimitry Andric # endif 73bdd1243dSDimitry Andric } 74bdd1243dSDimitry Andric 75bdd1243dSDimitry Andric } // namespace __expected 76bdd1243dSDimitry Andric 77bdd1243dSDimitry Andric template <class _Tp, class _Err> 78bdd1243dSDimitry Andric class expected { 79bdd1243dSDimitry Andric static_assert( 80bdd1243dSDimitry Andric !is_reference_v<_Tp> && 81bdd1243dSDimitry Andric !is_function_v<_Tp> && 82bdd1243dSDimitry Andric !is_same_v<remove_cv_t<_Tp>, in_place_t> && 83bdd1243dSDimitry Andric !is_same_v<remove_cv_t<_Tp>, unexpect_t> && 84bdd1243dSDimitry Andric !__is_std_unexpected<remove_cv_t<_Tp>>::value && 85bdd1243dSDimitry Andric __valid_std_unexpected<_Err>::value 86bdd1243dSDimitry Andric , 87bdd1243dSDimitry Andric "[expected.object.general] A program that instantiates the definition of template expected<T, E> for a " 88bdd1243dSDimitry Andric "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a " 89bdd1243dSDimitry Andric "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the " 90bdd1243dSDimitry Andric "definition of the template expected<T, E> with a type for the E parameter that is not a valid " 91bdd1243dSDimitry Andric "template argument for unexpected is ill-formed."); 92bdd1243dSDimitry Andric 93bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 94bdd1243dSDimitry Andric friend class expected; 95bdd1243dSDimitry Andric 96bdd1243dSDimitry Andric public: 97bdd1243dSDimitry Andric using value_type = _Tp; 98bdd1243dSDimitry Andric using error_type = _Err; 99bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 100bdd1243dSDimitry Andric 101bdd1243dSDimitry Andric template <class _Up> 102bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 103bdd1243dSDimitry Andric 104bdd1243dSDimitry Andric // [expected.object.ctor], constructors 105bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() 106bdd1243dSDimitry Andric noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened 107bdd1243dSDimitry Andric requires is_default_constructible_v<_Tp> 108bdd1243dSDimitry Andric : __has_val_(true) { 109bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_)); 110bdd1243dSDimitry Andric } 111bdd1243dSDimitry Andric 112bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 113bdd1243dSDimitry Andric 114bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 115bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Tp> && 116bdd1243dSDimitry Andric is_copy_constructible_v<_Err> && 117bdd1243dSDimitry Andric is_trivially_copy_constructible_v<_Tp> && 118bdd1243dSDimitry Andric is_trivially_copy_constructible_v<_Err>) 119bdd1243dSDimitry Andric = default; 120bdd1243dSDimitry Andric 121bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) 122bdd1243dSDimitry Andric noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened 123bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && 124bdd1243dSDimitry Andric !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)) 125bdd1243dSDimitry Andric : __has_val_(__other.__has_val_) { 126bdd1243dSDimitry Andric if (__has_val_) { 127bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_); 128bdd1243dSDimitry Andric } else { 129bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_); 130bdd1243dSDimitry Andric } 131bdd1243dSDimitry Andric } 132bdd1243dSDimitry Andric 133bdd1243dSDimitry Andric 134bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 135bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> 136bdd1243dSDimitry Andric && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>) 137bdd1243dSDimitry Andric = default; 138bdd1243dSDimitry Andric 139bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) 140bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) 141bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && 142bdd1243dSDimitry Andric !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)) 143bdd1243dSDimitry Andric : __has_val_(__other.__has_val_) { 144bdd1243dSDimitry Andric if (__has_val_) { 145bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_)); 146bdd1243dSDimitry Andric } else { 147bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_)); 148bdd1243dSDimitry Andric } 149bdd1243dSDimitry Andric } 150bdd1243dSDimitry Andric 151bdd1243dSDimitry Andric private: 152bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual> 153bdd1243dSDimitry Andric using __can_convert = 154bdd1243dSDimitry Andric _And< is_constructible<_Tp, _UfQual>, 155bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 156bdd1243dSDimitry Andric _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>, 157bdd1243dSDimitry Andric _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>, 158bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>, 159bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>, 160bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>, 161bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>, 162bdd1243dSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>, 163bdd1243dSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>, 164bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 165bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 166bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 167bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >; 168bdd1243dSDimitry Andric 169bdd1243dSDimitry Andric 170bdd1243dSDimitry Andric public: 171bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 172bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value 173bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> || 174bdd1243dSDimitry Andric !is_convertible_v<const _OtherErr&, _Err>) 175bdd1243dSDimitry Andric expected(const expected<_Up, _OtherErr>& __other) 176bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, const _Up&> && 177bdd1243dSDimitry Andric is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 178bdd1243dSDimitry Andric : __has_val_(__other.__has_val_) { 179bdd1243dSDimitry Andric if (__has_val_) { 180bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_); 181bdd1243dSDimitry Andric } else { 182bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_); 183bdd1243dSDimitry Andric } 184bdd1243dSDimitry Andric } 185bdd1243dSDimitry Andric 186bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 187bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value 188bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>) 189bdd1243dSDimitry Andric expected(expected<_Up, _OtherErr>&& __other) 190bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 191bdd1243dSDimitry Andric : __has_val_(__other.__has_val_) { 192bdd1243dSDimitry Andric if (__has_val_) { 193bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_)); 194bdd1243dSDimitry Andric } else { 195bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_)); 196bdd1243dSDimitry Andric } 197bdd1243dSDimitry Andric } 198bdd1243dSDimitry Andric 199bdd1243dSDimitry Andric template <class _Up = _Tp> 200bdd1243dSDimitry Andric requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> && 201bdd1243dSDimitry Andric !__is_std_unexpected<remove_cvref_t<_Up>>::value && is_constructible_v<_Tp, _Up>) 202bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>) 203bdd1243dSDimitry Andric expected(_Up&& __u) 204bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened 205bdd1243dSDimitry Andric : __has_val_(true) { 206bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_), std::forward<_Up>(__u)); 207bdd1243dSDimitry Andric } 208bdd1243dSDimitry Andric 209bdd1243dSDimitry Andric 210bdd1243dSDimitry Andric template <class _OtherErr> 211bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 212bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 213bdd1243dSDimitry Andric expected(const unexpected<_OtherErr>& __unex) 214bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 215bdd1243dSDimitry Andric : __has_val_(false) { 216bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __unex.error()); 217bdd1243dSDimitry Andric } 218bdd1243dSDimitry Andric 219bdd1243dSDimitry Andric template <class _OtherErr> 220bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 221bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 222bdd1243dSDimitry Andric expected(unexpected<_OtherErr>&& __unex) 223bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 224bdd1243dSDimitry Andric : __has_val_(false) { 225bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error())); 226bdd1243dSDimitry Andric } 227bdd1243dSDimitry Andric 228bdd1243dSDimitry Andric template <class... _Args> 229bdd1243dSDimitry Andric requires is_constructible_v<_Tp, _Args...> 230bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) 231bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened 232bdd1243dSDimitry Andric : __has_val_(true) { 233bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...); 234bdd1243dSDimitry Andric } 235bdd1243dSDimitry Andric 236bdd1243dSDimitry Andric template <class _Up, class... _Args> 237bdd1243dSDimitry Andric requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... > 238bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit 239bdd1243dSDimitry Andric expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 240bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened 241bdd1243dSDimitry Andric : __has_val_(true) { 242bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...); 243bdd1243dSDimitry Andric } 244bdd1243dSDimitry Andric 245bdd1243dSDimitry Andric template <class... _Args> 246bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 247bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) 248bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened 249bdd1243dSDimitry Andric : __has_val_(false) { 250bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...); 251bdd1243dSDimitry Andric } 252bdd1243dSDimitry Andric 253bdd1243dSDimitry Andric template <class _Up, class... _Args> 254bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 255bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit 256bdd1243dSDimitry Andric expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) 257bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 258bdd1243dSDimitry Andric : __has_val_(false) { 259bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...); 260bdd1243dSDimitry Andric } 261bdd1243dSDimitry Andric 262bdd1243dSDimitry Andric // [expected.object.dtor], destructor 263bdd1243dSDimitry Andric 264bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 265bdd1243dSDimitry Andric requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) 266bdd1243dSDimitry Andric = default; 267bdd1243dSDimitry Andric 268bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 269bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) 270bdd1243dSDimitry Andric { 271bdd1243dSDimitry Andric if (__has_val_) { 272bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 273bdd1243dSDimitry Andric } else { 274bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 275bdd1243dSDimitry Andric } 276bdd1243dSDimitry Andric } 277bdd1243dSDimitry Andric 278bdd1243dSDimitry Andric private: 279bdd1243dSDimitry Andric template <class _T1, class _T2, class... _Args> 280bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) { 281bdd1243dSDimitry Andric if constexpr (is_nothrow_constructible_v<_T1, _Args...>) { 282bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 283bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); 284bdd1243dSDimitry Andric } else if constexpr (is_nothrow_move_constructible_v<_T1>) { 285bdd1243dSDimitry Andric _T1 __tmp(std::forward<_Args>(__args)...); 286bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 287bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::move(__tmp)); 288bdd1243dSDimitry Andric } else { 289bdd1243dSDimitry Andric static_assert( 290bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_T2>, 291bdd1243dSDimitry Andric "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can " 292bdd1243dSDimitry Andric "be reverted to the previous state in case an exception is thrown during the assignment."); 293bdd1243dSDimitry Andric _T2 __tmp(std::move(__oldval)); 294bdd1243dSDimitry Andric std::destroy_at(std::addressof(__oldval)); 295*1ac55f4cSDimitry Andric auto __trans = 296*1ac55f4cSDimitry Andric std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); 297bdd1243dSDimitry Andric std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); 298bdd1243dSDimitry Andric __trans.__complete(); 299bdd1243dSDimitry Andric } 300bdd1243dSDimitry Andric } 301bdd1243dSDimitry Andric 302bdd1243dSDimitry Andric public: 303bdd1243dSDimitry Andric // [expected.object.assign], assignment 304bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 305bdd1243dSDimitry Andric 306bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) 307bdd1243dSDimitry Andric noexcept(is_nothrow_copy_assignable_v<_Tp> && 308bdd1243dSDimitry Andric is_nothrow_copy_constructible_v<_Tp> && 309bdd1243dSDimitry Andric is_nothrow_copy_assignable_v<_Err> && 310bdd1243dSDimitry Andric is_nothrow_copy_constructible_v<_Err>) // strengthened 311bdd1243dSDimitry Andric requires(is_copy_assignable_v<_Tp> && 312bdd1243dSDimitry Andric is_copy_constructible_v<_Tp> && 313bdd1243dSDimitry Andric is_copy_assignable_v<_Err> && 314bdd1243dSDimitry Andric is_copy_constructible_v<_Err> && 315bdd1243dSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || 316bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 317bdd1243dSDimitry Andric { 318bdd1243dSDimitry Andric if (__has_val_ && __rhs.__has_val_) { 319bdd1243dSDimitry Andric __union_.__val_ = __rhs.__union_.__val_; 320bdd1243dSDimitry Andric } else if (__has_val_) { 321bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_); 322bdd1243dSDimitry Andric } else if (__rhs.__has_val_) { 323bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_); 324bdd1243dSDimitry Andric } else { 325bdd1243dSDimitry Andric __union_.__unex_ = __rhs.__union_.__unex_; 326bdd1243dSDimitry Andric } 327bdd1243dSDimitry Andric // note: only reached if no exception+rollback was done inside __reinit_expected 328bdd1243dSDimitry Andric __has_val_ = __rhs.__has_val_; 329bdd1243dSDimitry Andric return *this; 330bdd1243dSDimitry Andric } 331bdd1243dSDimitry Andric 332bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) 333bdd1243dSDimitry Andric noexcept(is_nothrow_move_assignable_v<_Tp> && 334bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Tp> && 335bdd1243dSDimitry Andric is_nothrow_move_assignable_v<_Err> && 336bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>) 337bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && 338bdd1243dSDimitry Andric is_move_assignable_v<_Tp> && 339bdd1243dSDimitry Andric is_move_constructible_v<_Err> && 340bdd1243dSDimitry Andric is_move_assignable_v<_Err> && 341bdd1243dSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || 342bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 343bdd1243dSDimitry Andric { 344bdd1243dSDimitry Andric if (__has_val_ && __rhs.__has_val_) { 345bdd1243dSDimitry Andric __union_.__val_ = std::move(__rhs.__union_.__val_); 346bdd1243dSDimitry Andric } else if (__has_val_) { 347bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_)); 348bdd1243dSDimitry Andric } else if (__rhs.__has_val_) { 349bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_)); 350bdd1243dSDimitry Andric } else { 351bdd1243dSDimitry Andric __union_.__unex_ = std::move(__rhs.__union_.__unex_); 352bdd1243dSDimitry Andric } 353bdd1243dSDimitry Andric // note: only reached if no exception+rollback was done inside __reinit_expected 354bdd1243dSDimitry Andric __has_val_ = __rhs.__has_val_; 355bdd1243dSDimitry Andric return *this; 356bdd1243dSDimitry Andric } 357bdd1243dSDimitry Andric 358bdd1243dSDimitry Andric template <class _Up = _Tp> 359bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v) 360bdd1243dSDimitry Andric requires(!is_same_v<expected, remove_cvref_t<_Up>> && 361bdd1243dSDimitry Andric !__is_std_unexpected<remove_cvref_t<_Up>>::value && 362bdd1243dSDimitry Andric is_constructible_v<_Tp, _Up> && 363bdd1243dSDimitry Andric is_assignable_v<_Tp&, _Up> && 364bdd1243dSDimitry Andric (is_nothrow_constructible_v<_Tp, _Up> || 365bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Tp> || 366bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 367bdd1243dSDimitry Andric { 368bdd1243dSDimitry Andric if (__has_val_) { 369bdd1243dSDimitry Andric __union_.__val_ = std::forward<_Up>(__v); 370bdd1243dSDimitry Andric } else { 371bdd1243dSDimitry Andric __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v)); 372bdd1243dSDimitry Andric __has_val_ = true; 373bdd1243dSDimitry Andric } 374bdd1243dSDimitry Andric return *this; 375bdd1243dSDimitry Andric } 376bdd1243dSDimitry Andric 377bdd1243dSDimitry Andric private: 378bdd1243dSDimitry Andric template <class _OtherErrQual> 379bdd1243dSDimitry Andric static constexpr bool __can_assign_from_unexpected = 380bdd1243dSDimitry Andric _And< is_constructible<_Err, _OtherErrQual>, 381bdd1243dSDimitry Andric is_assignable<_Err&, _OtherErrQual>, 382bdd1243dSDimitry Andric _Lazy<_Or, 383bdd1243dSDimitry Andric is_nothrow_constructible<_Err, _OtherErrQual>, 384bdd1243dSDimitry Andric is_nothrow_move_constructible<_Tp>, 385bdd1243dSDimitry Andric is_nothrow_move_constructible<_Err>> >::value; 386bdd1243dSDimitry Andric 387bdd1243dSDimitry Andric public: 388bdd1243dSDimitry Andric template <class _OtherErr> 389bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<const _OtherErr&>) 390bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 391bdd1243dSDimitry Andric if (__has_val_) { 392bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, __un.error()); 393bdd1243dSDimitry Andric __has_val_ = false; 394bdd1243dSDimitry Andric } else { 395bdd1243dSDimitry Andric __union_.__unex_ = __un.error(); 396bdd1243dSDimitry Andric } 397bdd1243dSDimitry Andric return *this; 398bdd1243dSDimitry Andric } 399bdd1243dSDimitry Andric 400bdd1243dSDimitry Andric template <class _OtherErr> 401bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<_OtherErr>) 402bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 403bdd1243dSDimitry Andric if (__has_val_) { 404bdd1243dSDimitry Andric __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error())); 405bdd1243dSDimitry Andric __has_val_ = false; 406bdd1243dSDimitry Andric } else { 407bdd1243dSDimitry Andric __union_.__unex_ = std::move(__un.error()); 408bdd1243dSDimitry Andric } 409bdd1243dSDimitry Andric return *this; 410bdd1243dSDimitry Andric } 411bdd1243dSDimitry Andric 412bdd1243dSDimitry Andric template <class... _Args> 413bdd1243dSDimitry Andric requires is_nothrow_constructible_v<_Tp, _Args...> 414bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept { 415bdd1243dSDimitry Andric if (__has_val_) { 416bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 417bdd1243dSDimitry Andric } else { 418bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 419bdd1243dSDimitry Andric __has_val_ = true; 420bdd1243dSDimitry Andric } 421bdd1243dSDimitry Andric return *std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...); 422bdd1243dSDimitry Andric } 423bdd1243dSDimitry Andric 424bdd1243dSDimitry Andric template <class _Up, class... _Args> 425bdd1243dSDimitry Andric requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... > 426bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept { 427bdd1243dSDimitry Andric if (__has_val_) { 428bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__val_)); 429bdd1243dSDimitry Andric } else { 430bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 431bdd1243dSDimitry Andric __has_val_ = true; 432bdd1243dSDimitry Andric } 433bdd1243dSDimitry Andric return *std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...); 434bdd1243dSDimitry Andric } 435bdd1243dSDimitry Andric 436bdd1243dSDimitry Andric 437bdd1243dSDimitry Andric public: 438bdd1243dSDimitry Andric // [expected.object.swap], swap 439bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) 440bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Tp> && 441bdd1243dSDimitry Andric is_nothrow_swappable_v<_Tp> && 442bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err> && 443bdd1243dSDimitry Andric is_nothrow_swappable_v<_Err>) 444bdd1243dSDimitry Andric requires(is_swappable_v<_Tp> && 445bdd1243dSDimitry Andric is_swappable_v<_Err> && 446bdd1243dSDimitry Andric is_move_constructible_v<_Tp> && 447bdd1243dSDimitry Andric is_move_constructible_v<_Err> && 448bdd1243dSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || 449bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 450bdd1243dSDimitry Andric { 451bdd1243dSDimitry Andric auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { 452bdd1243dSDimitry Andric if constexpr (is_nothrow_move_constructible_v<_Err>) { 453bdd1243dSDimitry Andric _Err __tmp(std::move(__with_err.__union_.__unex_)); 454bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 455*1ac55f4cSDimitry Andric auto __trans = std::__make_exception_guard([&] { 456bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp)); 457bdd1243dSDimitry Andric }); 458bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_)); 459bdd1243dSDimitry Andric __trans.__complete(); 460bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_val.__union_.__val_)); 461bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp)); 462bdd1243dSDimitry Andric } else { 463bdd1243dSDimitry Andric static_assert(is_nothrow_move_constructible_v<_Tp>, 464bdd1243dSDimitry Andric "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so " 465bdd1243dSDimitry Andric "that it can be reverted to the previous state in case an exception is thrown during swap."); 466bdd1243dSDimitry Andric _Tp __tmp(std::move(__with_val.__union_.__val_)); 467bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_val.__union_.__val_)); 468*1ac55f4cSDimitry Andric auto __trans = std::__make_exception_guard([&] { 469bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); 470bdd1243dSDimitry Andric }); 471bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); 472bdd1243dSDimitry Andric __trans.__complete(); 473bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 474bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp)); 475bdd1243dSDimitry Andric } 476bdd1243dSDimitry Andric __with_val.__has_val_ = false; 477bdd1243dSDimitry Andric __with_err.__has_val_ = true; 478bdd1243dSDimitry Andric }; 479bdd1243dSDimitry Andric 480bdd1243dSDimitry Andric if (__has_val_) { 481bdd1243dSDimitry Andric if (__rhs.__has_val_) { 482bdd1243dSDimitry Andric using std::swap; 483bdd1243dSDimitry Andric swap(__union_.__val_, __rhs.__union_.__val_); 484bdd1243dSDimitry Andric } else { 485bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 486bdd1243dSDimitry Andric } 487bdd1243dSDimitry Andric } else { 488bdd1243dSDimitry Andric if (__rhs.__has_val_) { 489bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 490bdd1243dSDimitry Andric } else { 491bdd1243dSDimitry Andric using std::swap; 492bdd1243dSDimitry Andric swap(__union_.__unex_, __rhs.__union_.__unex_); 493bdd1243dSDimitry Andric } 494bdd1243dSDimitry Andric } 495bdd1243dSDimitry Andric } 496bdd1243dSDimitry Andric 497bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) 498bdd1243dSDimitry Andric noexcept(noexcept(__x.swap(__y))) 499bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 500bdd1243dSDimitry Andric { 501bdd1243dSDimitry Andric __x.swap(__y); 502bdd1243dSDimitry Andric } 503bdd1243dSDimitry Andric 504bdd1243dSDimitry Andric // [expected.object.obs], observers 505bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { 506bdd1243dSDimitry Andric _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); 507bdd1243dSDimitry Andric return std::addressof(__union_.__val_); 508bdd1243dSDimitry Andric } 509bdd1243dSDimitry Andric 510bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { 511bdd1243dSDimitry Andric _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); 512bdd1243dSDimitry Andric return std::addressof(__union_.__val_); 513bdd1243dSDimitry Andric } 514bdd1243dSDimitry Andric 515bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { 516bdd1243dSDimitry Andric _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); 517bdd1243dSDimitry Andric return __union_.__val_; 518bdd1243dSDimitry Andric } 519bdd1243dSDimitry Andric 520bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { 521bdd1243dSDimitry Andric _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); 522bdd1243dSDimitry Andric return __union_.__val_; 523bdd1243dSDimitry Andric } 524bdd1243dSDimitry Andric 525bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { 526bdd1243dSDimitry Andric _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); 527bdd1243dSDimitry Andric return std::move(__union_.__val_); 528bdd1243dSDimitry Andric } 529bdd1243dSDimitry Andric 530bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { 531bdd1243dSDimitry Andric _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); 532bdd1243dSDimitry Andric return std::move(__union_.__val_); 533bdd1243dSDimitry Andric } 534bdd1243dSDimitry Andric 535bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } 536bdd1243dSDimitry Andric 537bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } 538bdd1243dSDimitry Andric 539bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { 540bdd1243dSDimitry Andric if (!__has_val_) { 541bdd1243dSDimitry Andric __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); 542bdd1243dSDimitry Andric } 543bdd1243dSDimitry Andric return __union_.__val_; 544bdd1243dSDimitry Andric } 545bdd1243dSDimitry Andric 546bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { 547bdd1243dSDimitry Andric if (!__has_val_) { 548bdd1243dSDimitry Andric __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); 549bdd1243dSDimitry Andric } 550bdd1243dSDimitry Andric return __union_.__val_; 551bdd1243dSDimitry Andric } 552bdd1243dSDimitry Andric 553bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { 554bdd1243dSDimitry Andric if (!__has_val_) { 555bdd1243dSDimitry Andric __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); 556bdd1243dSDimitry Andric } 557bdd1243dSDimitry Andric return std::move(__union_.__val_); 558bdd1243dSDimitry Andric } 559bdd1243dSDimitry Andric 560bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { 561bdd1243dSDimitry Andric if (!__has_val_) { 562bdd1243dSDimitry Andric __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); 563bdd1243dSDimitry Andric } 564bdd1243dSDimitry Andric return std::move(__union_.__val_); 565bdd1243dSDimitry Andric } 566bdd1243dSDimitry Andric 567bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 568bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 569bdd1243dSDimitry Andric return __union_.__unex_; 570bdd1243dSDimitry Andric } 571bdd1243dSDimitry Andric 572bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 573bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 574bdd1243dSDimitry Andric return __union_.__unex_; 575bdd1243dSDimitry Andric } 576bdd1243dSDimitry Andric 577bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 578bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 579bdd1243dSDimitry Andric return std::move(__union_.__unex_); 580bdd1243dSDimitry Andric } 581bdd1243dSDimitry Andric 582bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 583bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 584bdd1243dSDimitry Andric return std::move(__union_.__unex_); 585bdd1243dSDimitry Andric } 586bdd1243dSDimitry Andric 587bdd1243dSDimitry Andric template <class _Up> 588bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { 589bdd1243dSDimitry Andric static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); 590bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 591bdd1243dSDimitry Andric return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v)); 592bdd1243dSDimitry Andric } 593bdd1243dSDimitry Andric 594bdd1243dSDimitry Andric template <class _Up> 595bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { 596bdd1243dSDimitry Andric static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); 597bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 598bdd1243dSDimitry Andric return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v)); 599bdd1243dSDimitry Andric } 600bdd1243dSDimitry Andric 601bdd1243dSDimitry Andric // [expected.object.eq], equality operators 602bdd1243dSDimitry Andric template <class _T2, class _E2> 603bdd1243dSDimitry Andric requires(!is_void_v<_T2>) 604bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 605bdd1243dSDimitry Andric if (__x.__has_val_ != __y.__has_val_) { 606bdd1243dSDimitry Andric return false; 607bdd1243dSDimitry Andric } else { 608bdd1243dSDimitry Andric if (__x.__has_val_) { 609bdd1243dSDimitry Andric return __x.__union_.__val_ == __y.__union_.__val_; 610bdd1243dSDimitry Andric } else { 611bdd1243dSDimitry Andric return __x.__union_.__unex_ == __y.__union_.__unex_; 612bdd1243dSDimitry Andric } 613bdd1243dSDimitry Andric } 614bdd1243dSDimitry Andric } 615bdd1243dSDimitry Andric 616bdd1243dSDimitry Andric template <class _T2> 617bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { 618bdd1243dSDimitry Andric return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v); 619bdd1243dSDimitry Andric } 620bdd1243dSDimitry Andric 621bdd1243dSDimitry Andric template <class _E2> 622bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { 623bdd1243dSDimitry Andric return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error()); 624bdd1243dSDimitry Andric } 625bdd1243dSDimitry Andric 626bdd1243dSDimitry Andric private: 627bdd1243dSDimitry Andric struct __empty_t {}; 628bdd1243dSDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union 629bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { 630bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} 631bdd1243dSDimitry Andric 632bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 633bdd1243dSDimitry Andric requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) 634bdd1243dSDimitry Andric = default; 635bdd1243dSDimitry Andric 636bdd1243dSDimitry Andric // the expected's destructor handles this 637bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 638bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) 639bdd1243dSDimitry Andric {} 640bdd1243dSDimitry Andric 641bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; 642bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; 643bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; 644bdd1243dSDimitry Andric } __union_; 645bdd1243dSDimitry Andric 646bdd1243dSDimitry Andric bool __has_val_; 647bdd1243dSDimitry Andric }; 648bdd1243dSDimitry Andric 649bdd1243dSDimitry Andric template <class _Tp, class _Err> 650bdd1243dSDimitry Andric requires is_void_v<_Tp> 651bdd1243dSDimitry Andric class expected<_Tp, _Err> { 652bdd1243dSDimitry Andric static_assert(__valid_std_unexpected<_Err>::value, 653bdd1243dSDimitry Andric "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a " 654bdd1243dSDimitry Andric "valid argument for unexpected<E> is ill-formed"); 655bdd1243dSDimitry Andric 656bdd1243dSDimitry Andric template <class, class> 657bdd1243dSDimitry Andric friend class expected; 658bdd1243dSDimitry Andric 659bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _OtherErrQual> 660bdd1243dSDimitry Andric using __can_convert = 661bdd1243dSDimitry Andric _And< is_void<_Up>, 662bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 663bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 664bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 665bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 666bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>; 667bdd1243dSDimitry Andric 668bdd1243dSDimitry Andric public: 669bdd1243dSDimitry Andric using value_type = _Tp; 670bdd1243dSDimitry Andric using error_type = _Err; 671bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 672bdd1243dSDimitry Andric 673bdd1243dSDimitry Andric template <class _Up> 674bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 675bdd1243dSDimitry Andric 676bdd1243dSDimitry Andric // [expected.void.ctor], constructors 677bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {} 678bdd1243dSDimitry Andric 679bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 680bdd1243dSDimitry Andric 681bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 682bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) 683bdd1243dSDimitry Andric = default; 684bdd1243dSDimitry Andric 685bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) 686bdd1243dSDimitry Andric noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened 687bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>) 688bdd1243dSDimitry Andric : __has_val_(__rhs.__has_val_) { 689bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 690bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); 691bdd1243dSDimitry Andric } 692bdd1243dSDimitry Andric } 693bdd1243dSDimitry Andric 694bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 695bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) 696bdd1243dSDimitry Andric = default; 697bdd1243dSDimitry Andric 698bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) 699bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Err>) 700bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>) 701bdd1243dSDimitry Andric : __has_val_(__rhs.__has_val_) { 702bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 703bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); 704bdd1243dSDimitry Andric } 705bdd1243dSDimitry Andric } 706bdd1243dSDimitry Andric 707bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 708bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value 709bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 710bdd1243dSDimitry Andric expected(const expected<_Up, _OtherErr>& __rhs) 711bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 712bdd1243dSDimitry Andric : __has_val_(__rhs.__has_val_) { 713bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 714bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); 715bdd1243dSDimitry Andric } 716bdd1243dSDimitry Andric } 717bdd1243dSDimitry Andric 718bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 719bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _OtherErr>::value 720bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 721bdd1243dSDimitry Andric expected(expected<_Up, _OtherErr>&& __rhs) 722bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 723bdd1243dSDimitry Andric : __has_val_(__rhs.__has_val_) { 724bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 725bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); 726bdd1243dSDimitry Andric } 727bdd1243dSDimitry Andric } 728bdd1243dSDimitry Andric 729bdd1243dSDimitry Andric template <class _OtherErr> 730bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 731bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 732bdd1243dSDimitry Andric expected(const unexpected<_OtherErr>& __unex) 733bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 734bdd1243dSDimitry Andric : __has_val_(false) { 735bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __unex.error()); 736bdd1243dSDimitry Andric } 737bdd1243dSDimitry Andric 738bdd1243dSDimitry Andric template <class _OtherErr> 739bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 740bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 741bdd1243dSDimitry Andric expected(unexpected<_OtherErr>&& __unex) 742bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 743bdd1243dSDimitry Andric : __has_val_(false) { 744bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error())); 745bdd1243dSDimitry Andric } 746bdd1243dSDimitry Andric 747bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {} 748bdd1243dSDimitry Andric 749bdd1243dSDimitry Andric template <class... _Args> 750bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 751bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) 752bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened 753bdd1243dSDimitry Andric : __has_val_(false) { 754bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...); 755bdd1243dSDimitry Andric } 756bdd1243dSDimitry Andric 757bdd1243dSDimitry Andric template <class _Up, class... _Args> 758bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 759bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) 760bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 761bdd1243dSDimitry Andric : __has_val_(false) { 762bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...); 763bdd1243dSDimitry Andric } 764bdd1243dSDimitry Andric 765bdd1243dSDimitry Andric // [expected.void.dtor], destructor 766bdd1243dSDimitry Andric 767bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 768bdd1243dSDimitry Andric requires is_trivially_destructible_v<_Err> 769bdd1243dSDimitry Andric = default; 770bdd1243dSDimitry Andric 771bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() 772bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Err>) 773bdd1243dSDimitry Andric { 774bdd1243dSDimitry Andric if (!__has_val_) { 775bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 776bdd1243dSDimitry Andric } 777bdd1243dSDimitry Andric } 778bdd1243dSDimitry Andric 779bdd1243dSDimitry Andric // [expected.void.assign], assignment 780bdd1243dSDimitry Andric 781bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 782bdd1243dSDimitry Andric 783bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) 784bdd1243dSDimitry Andric noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened 785bdd1243dSDimitry Andric requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>) 786bdd1243dSDimitry Andric { 787bdd1243dSDimitry Andric if (__has_val_) { 788bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 789bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); 790bdd1243dSDimitry Andric __has_val_ = false; 791bdd1243dSDimitry Andric } 792bdd1243dSDimitry Andric } else { 793bdd1243dSDimitry Andric if (__rhs.__has_val_) { 794bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 795bdd1243dSDimitry Andric __has_val_ = true; 796bdd1243dSDimitry Andric } else { 797bdd1243dSDimitry Andric __union_.__unex_ = __rhs.__union_.__unex_; 798bdd1243dSDimitry Andric } 799bdd1243dSDimitry Andric } 800bdd1243dSDimitry Andric return *this; 801bdd1243dSDimitry Andric } 802bdd1243dSDimitry Andric 803bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete; 804bdd1243dSDimitry Andric 805bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) 806bdd1243dSDimitry Andric noexcept(is_nothrow_move_assignable_v<_Err> && 807bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>) 808bdd1243dSDimitry Andric requires(is_move_assignable_v<_Err> && 809bdd1243dSDimitry Andric is_move_constructible_v<_Err>) 810bdd1243dSDimitry Andric { 811bdd1243dSDimitry Andric if (__has_val_) { 812bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 813bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); 814bdd1243dSDimitry Andric __has_val_ = false; 815bdd1243dSDimitry Andric } 816bdd1243dSDimitry Andric } else { 817bdd1243dSDimitry Andric if (__rhs.__has_val_) { 818bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 819bdd1243dSDimitry Andric __has_val_ = true; 820bdd1243dSDimitry Andric } else { 821bdd1243dSDimitry Andric __union_.__unex_ = std::move(__rhs.__union_.__unex_); 822bdd1243dSDimitry Andric } 823bdd1243dSDimitry Andric } 824bdd1243dSDimitry Andric return *this; 825bdd1243dSDimitry Andric } 826bdd1243dSDimitry Andric 827bdd1243dSDimitry Andric template <class _OtherErr> 828bdd1243dSDimitry Andric requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>) 829bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 830bdd1243dSDimitry Andric if (__has_val_) { 831bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), __un.error()); 832bdd1243dSDimitry Andric __has_val_ = false; 833bdd1243dSDimitry Andric } else { 834bdd1243dSDimitry Andric __union_.__unex_ = __un.error(); 835bdd1243dSDimitry Andric } 836bdd1243dSDimitry Andric return *this; 837bdd1243dSDimitry Andric } 838bdd1243dSDimitry Andric 839bdd1243dSDimitry Andric template <class _OtherErr> 840bdd1243dSDimitry Andric requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>) 841bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 842bdd1243dSDimitry Andric if (__has_val_) { 843bdd1243dSDimitry Andric std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error())); 844bdd1243dSDimitry Andric __has_val_ = false; 845bdd1243dSDimitry Andric } else { 846bdd1243dSDimitry Andric __union_.__unex_ = std::move(__un.error()); 847bdd1243dSDimitry Andric } 848bdd1243dSDimitry Andric return *this; 849bdd1243dSDimitry Andric } 850bdd1243dSDimitry Andric 851bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept { 852bdd1243dSDimitry Andric if (!__has_val_) { 853bdd1243dSDimitry Andric std::destroy_at(std::addressof(__union_.__unex_)); 854bdd1243dSDimitry Andric __has_val_ = true; 855bdd1243dSDimitry Andric } 856bdd1243dSDimitry Andric } 857bdd1243dSDimitry Andric 858bdd1243dSDimitry Andric // [expected.void.swap], swap 859bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) 860bdd1243dSDimitry Andric noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) 861bdd1243dSDimitry Andric requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>) 862bdd1243dSDimitry Andric { 863bdd1243dSDimitry Andric auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { 864bdd1243dSDimitry Andric std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); 865bdd1243dSDimitry Andric std::destroy_at(std::addressof(__with_err.__union_.__unex_)); 866bdd1243dSDimitry Andric __with_val.__has_val_ = false; 867bdd1243dSDimitry Andric __with_err.__has_val_ = true; 868bdd1243dSDimitry Andric }; 869bdd1243dSDimitry Andric 870bdd1243dSDimitry Andric if (__has_val_) { 871bdd1243dSDimitry Andric if (!__rhs.__has_val_) { 872bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 873bdd1243dSDimitry Andric } 874bdd1243dSDimitry Andric } else { 875bdd1243dSDimitry Andric if (__rhs.__has_val_) { 876bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 877bdd1243dSDimitry Andric } else { 878bdd1243dSDimitry Andric using std::swap; 879bdd1243dSDimitry Andric swap(__union_.__unex_, __rhs.__union_.__unex_); 880bdd1243dSDimitry Andric } 881bdd1243dSDimitry Andric } 882bdd1243dSDimitry Andric } 883bdd1243dSDimitry Andric 884bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) 885bdd1243dSDimitry Andric noexcept(noexcept(__x.swap(__y))) 886bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 887bdd1243dSDimitry Andric { 888bdd1243dSDimitry Andric __x.swap(__y); 889bdd1243dSDimitry Andric } 890bdd1243dSDimitry Andric 891bdd1243dSDimitry Andric // [expected.void.obs], observers 892bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } 893bdd1243dSDimitry Andric 894bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } 895bdd1243dSDimitry Andric 896bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { 897bdd1243dSDimitry Andric _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); 898bdd1243dSDimitry Andric } 899bdd1243dSDimitry Andric 900bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { 901bdd1243dSDimitry Andric if (!__has_val_) { 902bdd1243dSDimitry Andric __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); 903bdd1243dSDimitry Andric } 904bdd1243dSDimitry Andric } 905bdd1243dSDimitry Andric 906bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() && { 907bdd1243dSDimitry Andric if (!__has_val_) { 908bdd1243dSDimitry Andric __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); 909bdd1243dSDimitry Andric } 910bdd1243dSDimitry Andric } 911bdd1243dSDimitry Andric 912bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 913bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 914bdd1243dSDimitry Andric return __union_.__unex_; 915bdd1243dSDimitry Andric } 916bdd1243dSDimitry Andric 917bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 918bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 919bdd1243dSDimitry Andric return __union_.__unex_; 920bdd1243dSDimitry Andric } 921bdd1243dSDimitry Andric 922bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 923bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 924bdd1243dSDimitry Andric return std::move(__union_.__unex_); 925bdd1243dSDimitry Andric } 926bdd1243dSDimitry Andric 927bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 928bdd1243dSDimitry Andric _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); 929bdd1243dSDimitry Andric return std::move(__union_.__unex_); 930bdd1243dSDimitry Andric } 931bdd1243dSDimitry Andric 932bdd1243dSDimitry Andric // [expected.void.eq], equality operators 933bdd1243dSDimitry Andric template <class _T2, class _E2> 934bdd1243dSDimitry Andric requires is_void_v<_T2> 935bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 936bdd1243dSDimitry Andric if (__x.__has_val_ != __y.__has_val_) { 937bdd1243dSDimitry Andric return false; 938bdd1243dSDimitry Andric } else { 939bdd1243dSDimitry Andric return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_); 940bdd1243dSDimitry Andric } 941bdd1243dSDimitry Andric } 942bdd1243dSDimitry Andric 943bdd1243dSDimitry Andric template <class _E2> 944bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { 945bdd1243dSDimitry Andric return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error()); 946bdd1243dSDimitry Andric } 947bdd1243dSDimitry Andric 948bdd1243dSDimitry Andric private: 949bdd1243dSDimitry Andric struct __empty_t {}; 950bdd1243dSDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union 951bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { 952bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} 953bdd1243dSDimitry Andric 954bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 955bdd1243dSDimitry Andric requires(is_trivially_destructible_v<_Err>) 956bdd1243dSDimitry Andric = default; 957bdd1243dSDimitry Andric 958bdd1243dSDimitry Andric // the expected's destructor handles this 959bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 960bdd1243dSDimitry Andric requires(!is_trivially_destructible_v<_Err>) 961bdd1243dSDimitry Andric {} 962bdd1243dSDimitry Andric 963bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; 964bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; 965bdd1243dSDimitry Andric } __union_; 966bdd1243dSDimitry Andric 967bdd1243dSDimitry Andric bool __has_val_; 968bdd1243dSDimitry Andric }; 969bdd1243dSDimitry Andric 970bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD 971bdd1243dSDimitry Andric 972bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 23 973bdd1243dSDimitry Andric 974bdd1243dSDimitry Andric #endif // _LIBCPP___EXPECTED_EXPECTED_H 975