// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP___EXPECTED_EXPECTED_H #define _LIBCPP___EXPECTED_EXPECTED_H #include <__assert> #include <__config> #include <__expected/bad_expected_access.h> #include <__expected/unexpect.h> #include <__expected/unexpected.h> #include <__functional/invoke.h> #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__type_traits/conjunction.h> #include <__type_traits/disjunction.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_copy_assignable.h> #include <__type_traits/is_copy_constructible.h> #include <__type_traits/is_default_constructible.h> #include <__type_traits/is_function.h> #include <__type_traits/is_move_assignable.h> #include <__type_traits/is_move_constructible.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_nothrow_copy_assignable.h> #include <__type_traits/is_nothrow_copy_constructible.h> #include <__type_traits/is_nothrow_default_constructible.h> #include <__type_traits/is_nothrow_move_assignable.h> #include <__type_traits/is_nothrow_move_constructible.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_copy_constructible.h> #include <__type_traits/is_trivially_destructible.h> #include <__type_traits/is_trivially_move_constructible.h> #include <__type_traits/is_void.h> #include <__type_traits/lazy.h> #include <__type_traits/negation.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> #include <__utility/as_const.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> #include <__utility/swap.h> #include <__verbose_abort> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> #if _LIBCPP_STD_VER >= 23 _LIBCPP_BEGIN_NAMESPACE_STD template class expected; template struct __is_std_expected : false_type {}; template struct __is_std_expected> : true_type {}; struct __expected_construct_in_place_from_invoke_tag {}; struct __expected_construct_unexpected_from_invoke_tag {}; template _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) { # ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_expected_access<_Err>(std::forward<_Arg>(__arg)); # else (void)__arg; _LIBCPP_VERBOSE_ABORT("bad_expected_access was thrown in -fno-exceptions mode"); # endif } template class expected { static_assert( !is_reference_v<_Tp> && !is_function_v<_Tp> && !is_same_v, in_place_t> && !is_same_v, unexpect_t> && !__is_std_unexpected>::value && __valid_std_unexpected<_Err>::value , "[expected.object.general] A program that instantiates the definition of template expected for a " "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a " "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the " "definition of the template expected with a type for the E parameter that is not a valid " "template argument for unexpected is ill-formed."); template friend class expected; public: using value_type = _Tp; using error_type = _Err; using unexpected_type = unexpected<_Err>; template using rebind = expected<_Up, error_type>; // [expected.object.ctor], constructors _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened requires is_default_constructible_v<_Tp> : __union_(std::in_place), __has_val_(true) {} _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>) = default; _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)) : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) { } _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>) = default; _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)) : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) { } private: template using __can_convert = _And< is_constructible<_Tp, _UfQual>, is_constructible<_Err, _OtherErrQual>, _Not&>>, _Not>>, _Not&>>, _Not>>, _Not&, _Tp>>, _Not&&, _Tp>>, _Not&, _Tp>>, _Not&&, _Tp>>, _Not, expected<_Up, _OtherErr>&>>, _Not, expected<_Up, _OtherErr>>>, _Not, const expected<_Up, _OtherErr>&>>, _Not, const expected<_Up, _OtherErr>>> >; template _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(true) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} public: template requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v || !is_convertible_v) expected(const expected<_Up, _OtherErr>& __other) noexcept(is_nothrow_constructible_v<_Tp, const _Up&> && is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {} template requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>) expected(expected<_Up, _OtherErr>&& __other) noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {} template requires(!is_same_v, in_place_t> && !is_same_v> && !__is_std_unexpected>::value && is_constructible_v<_Tp, _Up>) _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>) expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened : __union_(std::in_place, std::forward<_Up>(__u)), __has_val_(true) {} template requires is_constructible_v<_Err, const _OtherErr&> _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) expected(const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened : __union_(std::unexpect, __unex.error()), __has_val_(false) {} template requires is_constructible_v<_Err, _OtherErr> _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {} template requires is_constructible_v<_Tp, _Args...> _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened : __union_(std::in_place, std::forward<_Args>(__args)...), __has_val_(true) {} template requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... > _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened : __union_(std::in_place, __il, std::forward<_Args>(__args)...), __has_val_(true) {} template requires is_constructible_v<_Err, _Args...> _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {} template requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {} // [expected.object.dtor], destructor _LIBCPP_HIDE_FROM_ABI constexpr ~expected() requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) = default; _LIBCPP_HIDE_FROM_ABI constexpr ~expected() requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) { if (__has_val_) { std::destroy_at(std::addressof(__union_.__val_)); } else { std::destroy_at(std::addressof(__union_.__unex_)); } } private: template _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) { if constexpr (is_nothrow_constructible_v<_T1, _Args...>) { std::destroy_at(std::addressof(__oldval)); std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); } else if constexpr (is_nothrow_move_constructible_v<_T1>) { _T1 __tmp(std::forward<_Args>(__args)...); std::destroy_at(std::addressof(__oldval)); std::construct_at(std::addressof(__newval), std::move(__tmp)); } else { static_assert( is_nothrow_move_constructible_v<_T2>, "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can " "be reverted to the previous state in case an exception is thrown during the assignment."); _T2 __tmp(std::move(__oldval)); std::destroy_at(std::addressof(__oldval)); auto __trans = std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); __trans.__complete(); } } public: // [expected.object.assign], assignment _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept(is_nothrow_copy_assignable_v<_Tp> && is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened requires(is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err> && (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) { if (__has_val_ && __rhs.__has_val_) { __union_.__val_ = __rhs.__union_.__val_; } else if (__has_val_) { __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_); } else if (__rhs.__has_val_) { __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_); } else { __union_.__unex_ = __rhs.__union_.__unex_; } // note: only reached if no exception+rollback was done inside __reinit_expected __has_val_ = __rhs.__has_val_; return *this; } _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Tp> && is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>) requires(is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp> && is_move_constructible_v<_Err> && is_move_assignable_v<_Err> && (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) { if (__has_val_ && __rhs.__has_val_) { __union_.__val_ = std::move(__rhs.__union_.__val_); } else if (__has_val_) { __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_)); } else if (__rhs.__has_val_) { __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_)); } else { __union_.__unex_ = std::move(__rhs.__union_.__unex_); } // note: only reached if no exception+rollback was done inside __reinit_expected __has_val_ = __rhs.__has_val_; return *this; } template _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v) requires(!is_same_v> && !__is_std_unexpected>::value && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> && (is_nothrow_constructible_v<_Tp, _Up> || is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) { if (__has_val_) { __union_.__val_ = std::forward<_Up>(__v); } else { __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v)); __has_val_ = true; } return *this; } private: template static constexpr bool __can_assign_from_unexpected = _And< is_constructible<_Err, _OtherErrQual>, is_assignable<_Err&, _OtherErrQual>, _Lazy<_Or, is_nothrow_constructible<_Err, _OtherErrQual>, is_nothrow_move_constructible<_Tp>, is_nothrow_move_constructible<_Err>> >::value; public: template requires(__can_assign_from_unexpected) _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { if (__has_val_) { __reinit_expected(__union_.__unex_, __union_.__val_, __un.error()); __has_val_ = false; } else { __union_.__unex_ = __un.error(); } return *this; } template requires(__can_assign_from_unexpected<_OtherErr>) _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { if (__has_val_) { __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error())); __has_val_ = false; } else { __union_.__unex_ = std::move(__un.error()); } return *this; } template requires is_nothrow_constructible_v<_Tp, _Args...> _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept { if (__has_val_) { std::destroy_at(std::addressof(__union_.__val_)); } else { std::destroy_at(std::addressof(__union_.__unex_)); } std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...); __has_val_ = true; return __union_.__val_; } template requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... > _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept { if (__has_val_) { std::destroy_at(std::addressof(__union_.__val_)); } else { std::destroy_at(std::addressof(__union_.__unex_)); } std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...); __has_val_ = true; return __union_.__val_; } public: // [expected.object.swap], swap _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) requires(is_swappable_v<_Tp> && is_swappable_v<_Err> && is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) { auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { if constexpr (is_nothrow_move_constructible_v<_Err>) { _Err __tmp(std::move(__with_err.__union_.__unex_)); std::destroy_at(std::addressof(__with_err.__union_.__unex_)); auto __trans = std::__make_exception_guard([&] { std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp)); }); std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_)); __trans.__complete(); std::destroy_at(std::addressof(__with_val.__union_.__val_)); std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp)); } else { static_assert(is_nothrow_move_constructible_v<_Tp>, "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so " "that it can be reverted to the previous state in case an exception is thrown during swap."); _Tp __tmp(std::move(__with_val.__union_.__val_)); std::destroy_at(std::addressof(__with_val.__union_.__val_)); auto __trans = std::__make_exception_guard([&] { std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); }); std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); __trans.__complete(); std::destroy_at(std::addressof(__with_err.__union_.__unex_)); std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp)); } __with_val.__has_val_ = false; __with_err.__has_val_ = true; }; if (__has_val_) { if (__rhs.__has_val_) { using std::swap; swap(__union_.__val_, __rhs.__union_.__val_); } else { __swap_val_unex_impl(*this, __rhs); } } else { if (__rhs.__has_val_) { __swap_val_unex_impl(__rhs, *this); } else { using std::swap; swap(__union_.__unex_, __rhs.__union_.__unex_); } } } _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y))) requires requires { __x.swap(__y); } { __x.swap(__y); } // [expected.object.obs], observers _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); return std::addressof(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); return std::addressof(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!__has_val_) { std::__throw_bad_expected_access<_Err>(std::as_const(error())); } return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!__has_val_) { std::__throw_bad_expected_access<_Err>(std::as_const(error())); } return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!__has_val_) { std::__throw_bad_expected_access<_Err>(std::move(error())); } return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!__has_val_) { std::__throw_bad_expected_access<_Err>(std::move(error())); } return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } template _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v)); } template _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v)); } template _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); if (has_value()) return std::forward<_Up>(__error); return error(); } template _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); if (has_value()) return std::forward<_Up>(__error); return std::move(error()); } // [expected.void.monadic], monadic template requires is_constructible_v<_Err, _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { using _Up = remove_cvref_t>; static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(value()) must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f), value()); } return _Up(unexpect, error()); } template requires is_constructible_v<_Err, const _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { using _Up = remove_cvref_t>; static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(value()) must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f), value()); } return _Up(unexpect, error()); } template requires is_constructible_v<_Err, _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { using _Up = remove_cvref_t>; static_assert( __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(std::move(value())) must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f), std::move(value())); } return _Up(unexpect, std::move(error())); } template requires is_constructible_v<_Err, const _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { using _Up = remove_cvref_t>; static_assert( __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(std::move(value())) must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f), std::move(value())); } return _Up(unexpect, std::move(error())); } template requires is_constructible_v<_Tp, _Tp&> _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { using _Gp = remove_cvref_t>; static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(error()) must have the same value_type as this expected"); if (has_value()) { return _Gp(in_place, value()); } return std::invoke(std::forward<_Func>(__f), error()); } template requires is_constructible_v<_Tp, const _Tp&> _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { using _Gp = remove_cvref_t>; static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(error()) must have the same value_type as this expected"); if (has_value()) { return _Gp(in_place, value()); } return std::invoke(std::forward<_Func>(__f), error()); } template requires is_constructible_v<_Tp, _Tp&&> _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { using _Gp = remove_cvref_t>; static_assert( __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(std::move(error())) must have the same value_type as this expected"); if (has_value()) { return _Gp(in_place, std::move(value())); } return std::invoke(std::forward<_Func>(__f), std::move(error())); } template requires is_constructible_v<_Tp, const _Tp&&> _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { using _Gp = remove_cvref_t>; static_assert( __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(std::move(error())) must have the same value_type as this expected"); if (has_value()) { return _Gp(in_place, std::move(value())); } return std::invoke(std::forward<_Func>(__f), std::move(error())); } template requires is_constructible_v<_Err, _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, error()); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); } else { std::invoke(std::forward<_Func>(__f), value()); return expected<_Up, _Err>(); } } template requires is_constructible_v<_Err, const _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, error()); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); } else { std::invoke(std::forward<_Func>(__f), value()); return expected<_Up, _Err>(); } } template requires is_constructible_v<_Err, _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, std::move(error())); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>( __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); } else { std::invoke(std::forward<_Func>(__f), std::move(value())); return expected<_Up, _Err>(); } } template requires is_constructible_v<_Err, const _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, std::move(error())); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>( __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); } else { std::invoke(std::forward<_Func>(__f), std::move(value())); return expected<_Up, _Err>(); } } template requires is_constructible_v<_Tp, _Tp&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(error()) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(in_place, value()); } return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); } template requires is_constructible_v<_Tp, const _Tp&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(error()) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(in_place, value()); } return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); } template requires is_constructible_v<_Tp, _Tp&&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(std::move(error())) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(in_place, std::move(value())); } return expected<_Tp, _Gp>( __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); } template requires is_constructible_v<_Tp, const _Tp&&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(std::move(error())) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(in_place, std::move(value())); } return expected<_Tp, _Gp>( __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); } // [expected.object.eq], equality operators template requires(!is_void_v<_T2>) _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { if (__x.__has_val_ != __y.__has_val_) { return false; } else { if (__x.__has_val_) { return __x.__union_.__val_ == __y.__union_.__val_; } else { return __x.__union_.__unex_ == __y.__union_.__unex_; } } } template _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { return __x.__has_val_ && static_cast(__x.__union_.__val_ == __v); } template _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __e.error()); } private: template union __union_t { template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args) : __val_(std::forward<_Args>(__args)...) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) : __unex_(std::forward<_Args>(__args)...) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { if (__has_val) std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_); else std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} _ValueType __val_; _ErrorType __unex_; }; // use named union because [[no_unique_address]] cannot be applied to an unnamed union, // also guaranteed elision into a potentially-overlapping subobject is unsettled (and // it's not clear that it's implementable, given that the function is allowed to clobber // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. template requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>) union __union_t<_ValueType, _ErrorType> { _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default; _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default; template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args) : __val_(std::forward<_Args>(__args)...) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) : __unex_(std::forward<_Args>(__args)...) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { if (__has_val) std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_); else std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>) {} _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_; _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; }; _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_; bool __has_val_; }; template requires is_void_v<_Tp> class expected<_Tp, _Err> { static_assert(__valid_std_unexpected<_Err>::value, "[expected.void.general] A program that instantiates expected with a E that is not a " "valid argument for unexpected is ill-formed"); template friend class expected; template using __can_convert = _And< is_void<_Up>, is_constructible<_Err, _OtherErrQual>, _Not, expected<_Up, _OtherErr>&>>, _Not, expected<_Up, _OtherErr>>>, _Not, const expected<_Up, _OtherErr>&>>, _Not, const expected<_Up, _OtherErr>>>>; public: using value_type = _Tp; using error_type = _Err; using unexpected_type = unexpected<_Err>; template using rebind = expected<_Up, error_type>; // [expected.void.ctor], constructors _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {} _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) = default; _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>) : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {} _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) = default; _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) noexcept(is_nothrow_move_constructible_v<_Err>) requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>) : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {} template requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) expected(const expected<_Up, _OtherErr>& __rhs) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {} template requires __can_convert<_Up, _OtherErr, _OtherErr>::value _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) expected(expected<_Up, _OtherErr>&& __rhs) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {} template requires is_constructible_v<_Err, const _OtherErr&> _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) expected(const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened : __union_(std::unexpect, __unex.error()), __has_val_(false) {} template requires is_constructible_v<_Err, _OtherErr> _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {} _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {} template requires is_constructible_v<_Err, _Args...> _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {} template requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {} private: template _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f) : __has_val_(true) { std::invoke(std::forward<_Func>(__f)); } template _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} public: // [expected.void.dtor], destructor _LIBCPP_HIDE_FROM_ABI constexpr ~expected() requires is_trivially_destructible_v<_Err> = default; _LIBCPP_HIDE_FROM_ABI constexpr ~expected() requires(!is_trivially_destructible_v<_Err>) { if (!__has_val_) { std::destroy_at(std::addressof(__union_.__unex_)); } } // [expected.void.assign], assignment _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>) { if (__has_val_) { if (!__rhs.__has_val_) { std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_); __has_val_ = false; } } else { if (__rhs.__has_val_) { std::destroy_at(std::addressof(__union_.__unex_)); __has_val_ = true; } else { __union_.__unex_ = __rhs.__union_.__unex_; } } return *this; } _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete; _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>) requires(is_move_assignable_v<_Err> && is_move_constructible_v<_Err>) { if (__has_val_) { if (!__rhs.__has_val_) { std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_)); __has_val_ = false; } } else { if (__rhs.__has_val_) { std::destroy_at(std::addressof(__union_.__unex_)); __has_val_ = true; } else { __union_.__unex_ = std::move(__rhs.__union_.__unex_); } } return *this; } template requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>) _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { if (__has_val_) { std::construct_at(std::addressof(__union_.__unex_), __un.error()); __has_val_ = false; } else { __union_.__unex_ = __un.error(); } return *this; } template requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>) _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { if (__has_val_) { std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error())); __has_val_ = false; } else { __union_.__unex_ = std::move(__un.error()); } return *this; } _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept { if (!__has_val_) { std::destroy_at(std::addressof(__union_.__unex_)); __has_val_ = true; } } // [expected.void.swap], swap _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>) { auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) { std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); std::destroy_at(std::addressof(__with_err.__union_.__unex_)); __with_val.__has_val_ = false; __with_err.__has_val_ = true; }; if (__has_val_) { if (!__rhs.__has_val_) { __swap_val_unex_impl(*this, __rhs); } } else { if (__rhs.__has_val_) { __swap_val_unex_impl(__rhs, *this); } else { using std::swap; swap(__union_.__unex_, __rhs.__union_.__unex_); } } } _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y))) requires requires { __x.swap(__y); } { __x.swap(__y); } // [expected.void.obs], observers _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); } _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { if (!__has_val_) { std::__throw_bad_expected_access<_Err>(__union_.__unex_); } } _LIBCPP_HIDE_FROM_ABI constexpr void value() && { if (!__has_val_) { std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); } } _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } template _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); if (has_value()) { return std::forward<_Up>(__error); } return error(); } template _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); if (has_value()) { return std::forward<_Up>(__error); } return std::move(error()); } // [expected.void.monadic], monadic template requires is_constructible_v<_Err, _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { using _Up = remove_cvref_t>; static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); static_assert( is_same_v, "The result of f() must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f)); } return _Up(unexpect, error()); } template requires is_constructible_v<_Err, const _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { using _Up = remove_cvref_t>; static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); static_assert( is_same_v, "The result of f() must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f)); } return _Up(unexpect, error()); } template requires is_constructible_v<_Err, _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { using _Up = remove_cvref_t>; static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); static_assert( is_same_v, "The result of f() must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f)); } return _Up(unexpect, std::move(error())); } template requires is_constructible_v<_Err, const _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { using _Up = remove_cvref_t>; static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); static_assert( is_same_v, "The result of f() must have the same error_type as this expected"); if (has_value()) { return std::invoke(std::forward<_Func>(__f)); } return _Up(unexpect, std::move(error())); } template _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { using _Gp = remove_cvref_t>; static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(error()) must have the same value_type as this expected"); if (has_value()) { return _Gp(); } return std::invoke(std::forward<_Func>(__f), error()); } template _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { using _Gp = remove_cvref_t>; static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(error()) must have the same value_type as this expected"); if (has_value()) { return _Gp(); } return std::invoke(std::forward<_Func>(__f), error()); } template _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { using _Gp = remove_cvref_t>; static_assert(__is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(std::move(error())) must have the same value_type as this expected"); if (has_value()) { return _Gp(); } return std::invoke(std::forward<_Func>(__f), std::move(error())); } template _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { using _Gp = remove_cvref_t>; static_assert(__is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); static_assert(is_same_v, "The result of f(std::move(error())) must have the same value_type as this expected"); if (has_value()) { return _Gp(); } return std::invoke(std::forward<_Func>(__f), std::move(error())); } template requires is_constructible_v<_Err, _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, error()); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); } else { std::invoke(std::forward<_Func>(__f)); return expected<_Up, _Err>(); } } template requires is_constructible_v<_Err, const _Err&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, error()); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); } else { std::invoke(std::forward<_Func>(__f)); return expected<_Up, _Err>(); } } template requires is_constructible_v<_Err, _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, std::move(error())); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); } else { std::invoke(std::forward<_Func>(__f)); return expected<_Up, _Err>(); } } template requires is_constructible_v<_Err, const _Err&&> _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { using _Up = remove_cv_t>; if (!has_value()) { return expected<_Up, _Err>(unexpect, std::move(error())); } if constexpr (!is_void_v<_Up>) { return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); } else { std::invoke(std::forward<_Func>(__f)); return expected<_Up, _Err>(); } } template _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(error()) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(); } return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); } template _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(error()) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(); } return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); } template _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(std::move(error())) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(); } return expected<_Tp, _Gp>( __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); } template _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { using _Gp = remove_cv_t>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(std::move(error())) must be a valid template argument for unexpected"); if (has_value()) { return expected<_Tp, _Gp>(); } return expected<_Tp, _Gp>( __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); } // [expected.void.eq], equality operators template requires is_void_v<_T2> _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { if (__x.__has_val_ != __y.__has_val_) { return false; } else { return __x.__has_val_ || static_cast(__x.__union_.__unex_ == __y.__union_.__unex_); } } template _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __y.error()); } private: struct __empty_t {}; template union __union_t { _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) : __unex_(std::forward<_Args>(__args)...) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { if (__has_val) std::construct_at(std::addressof(__empty_)); else std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() requires(is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} __empty_t __empty_; _ErrorType __unex_; }; // use named union because [[no_unique_address]] cannot be applied to an unnamed union, // also guaranteed elision into a potentially-overlapping subobject is unsettled (and // it's not clear that it's implementable, given that the function is allowed to clobber // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. template requires is_trivially_move_constructible_v<_ErrorType> union __union_t<_ErrorType> { _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args) : __unex_(std::forward<_Args>(__args)...) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} template _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) { if (__has_val) std::construct_at(std::addressof(__empty_)); else std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() requires(is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() requires(!is_trivially_destructible_v<_ErrorType>) {} _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; }; _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_; bool __has_val_; }; _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 _LIBCPP_POP_MACROS #endif // _LIBCPP___EXPECTED_EXPECTED_H