mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
9783f28cbb
This patch runs clang-format on all of libcxx/include and libcxx/src, in accordance with the RFC discussed at [1]. Follow-up patches will format the benchmarks, the test suite and remaining parts of the code. I'm splitting this one into its own patch so the diff is a bit easier to review. This patch was generated with: find libcxx/include libcxx/src -type f \ | grep -v 'module.modulemap.in' \ | grep -v 'CMakeLists.txt' \ | grep -v 'README.txt' \ | grep -v 'libcxx.imp' \ | grep -v '__config_site.in' \ | xargs clang-format -i A Git merge driver is available in libcxx/utils/clang-format-merge-driver.sh to help resolve merge and rebase issues across these formatting changes. [1]: https://discourse.llvm.org/t/rfc-clang-formatting-all-of-libc-once-and-for-all
1516 lines
64 KiB
C++
1516 lines
64 KiB
C++
// -*- 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 <initializer_list>
|
|
|
|
#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 _Tp, class _Err>
|
|
class expected;
|
|
|
|
template <class _Tp>
|
|
struct __is_std_expected : false_type {};
|
|
|
|
template <class _Tp, class _Err>
|
|
struct __is_std_expected<expected<_Tp, _Err>> : true_type {};
|
|
|
|
struct __expected_construct_in_place_from_invoke_tag {};
|
|
struct __expected_construct_unexpected_from_invoke_tag {};
|
|
|
|
template <class _Err, class _Arg>
|
|
_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 _Tp, class _Err>
|
|
class expected {
|
|
static_assert(!is_reference_v<_Tp> && !is_function_v<_Tp> && !is_same_v<remove_cv_t<_Tp>, in_place_t> &&
|
|
!is_same_v<remove_cv_t<_Tp>, unexpect_t> && !__is_std_unexpected<remove_cv_t<_Tp>>::value &&
|
|
__valid_std_unexpected<_Err>::value,
|
|
"[expected.object.general] A program that instantiates the definition of template expected<T, E> 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<T, E> with a type for the E parameter that is not a valid "
|
|
"template argument for unexpected is ill-formed.");
|
|
|
|
template <class _Up, class _OtherErr>
|
|
friend class expected;
|
|
|
|
public:
|
|
using value_type = _Tp;
|
|
using error_type = _Err;
|
|
using unexpected_type = unexpected<_Err>;
|
|
|
|
template <class _Up>
|
|
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 <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
|
|
using __can_convert =
|
|
_And< is_constructible<_Tp, _UfQual>,
|
|
is_constructible<_Err, _OtherErrQual>,
|
|
_If<_Not<is_same<remove_cv_t<_Tp>, bool>>::value,
|
|
_And< _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
|
|
_Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>,
|
|
_Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>,
|
|
_Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>,
|
|
_Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>,
|
|
_Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>,
|
|
_Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>,
|
|
_Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>>,
|
|
true_type>,
|
|
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
|
|
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
|
|
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
|
|
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >;
|
|
|
|
template <class _Func, class... _Args>
|
|
_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 <class _Func, class... _Args>
|
|
_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 <class _Up, class _OtherErr>
|
|
requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> ||
|
|
!is_convertible_v<const _OtherErr&, _Err>)
|
|
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 <class _Up, class _OtherErr>
|
|
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 <class _Up = _Tp>
|
|
requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
|
|
is_constructible_v<_Tp, _Up> && !__is_std_unexpected<remove_cvref_t<_Up>>::value &&
|
|
(!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value))
|
|
_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 <class _OtherErr>
|
|
requires is_constructible_v<_Err, const _OtherErr&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected(
|
|
const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
|
: __union_(std::unexpect, __unex.error()), __has_val_(false) {}
|
|
|
|
template <class _OtherErr>
|
|
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 <class... _Args>
|
|
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 <class _Up, class... _Args>
|
|
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 <class... _Args>
|
|
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 <class _Up, class... _Args>
|
|
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 <class _T1, class _T2, class... _Args>
|
|
_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 <class _Up = _Tp>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v)
|
|
requires(!is_same_v<expected, remove_cvref_t<_Up>> && !__is_std_unexpected<remove_cvref_t<_Up>>::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 <class _OtherErrQual>
|
|
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 <class _OtherErr>
|
|
requires(__can_assign_from_unexpected<const _OtherErr&>)
|
|
_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 <class _OtherErr>
|
|
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 <class... _Args>
|
|
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 <class _Up, class... _Args>
|
|
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 <class _Up>
|
|
_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 <class _Up>
|
|
_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 <class _Up = _Err>
|
|
_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 <class _Up = _Err>
|
|
_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 <class _Func>
|
|
requires is_constructible_v<_Err, _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>;
|
|
static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Up::error_type, _Err>,
|
|
"The result of f(**this) must have the same error_type as this expected");
|
|
if (has_value()) {
|
|
return std::invoke(std::forward<_Func>(__f), __union_.__val_);
|
|
}
|
|
return _Up(unexpect, error());
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>;
|
|
static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Up::error_type, _Err>,
|
|
"The result of f(**this) must have the same error_type as this expected");
|
|
if (has_value()) {
|
|
return std::invoke(std::forward<_Func>(__f), __union_.__val_);
|
|
}
|
|
return _Up(unexpect, error());
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Err, _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>;
|
|
static_assert(
|
|
__is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Up::error_type, _Err>,
|
|
"The result of f(std::move(**this)) must have the same error_type as this expected");
|
|
if (has_value()) {
|
|
return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
|
|
}
|
|
return _Up(unexpect, std::move(error()));
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>;
|
|
static_assert(
|
|
__is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Up::error_type, _Err>,
|
|
"The result of f(std::move(**this)) must have the same error_type as this expected");
|
|
if (has_value()) {
|
|
return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
|
|
}
|
|
return _Up(unexpect, std::move(error()));
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, _Tp&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>;
|
|
static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Gp::value_type, _Tp>,
|
|
"The result of f(error()) must have the same value_type as this expected");
|
|
if (has_value()) {
|
|
return _Gp(in_place, __union_.__val_);
|
|
}
|
|
return std::invoke(std::forward<_Func>(__f), error());
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, const _Tp&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>;
|
|
static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Gp::value_type, _Tp>,
|
|
"The result of f(error()) must have the same value_type as this expected");
|
|
if (has_value()) {
|
|
return _Gp(in_place, __union_.__val_);
|
|
}
|
|
return std::invoke(std::forward<_Func>(__f), error());
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, _Tp&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>;
|
|
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<typename _Gp::value_type, _Tp>,
|
|
"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(__union_.__val_));
|
|
}
|
|
return std::invoke(std::forward<_Func>(__f), std::move(error()));
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, const _Tp&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>;
|
|
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<typename _Gp::value_type, _Tp>,
|
|
"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(__union_.__val_));
|
|
}
|
|
return std::invoke(std::forward<_Func>(__f), std::move(error()));
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Err, _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
|
|
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), __union_.__val_);
|
|
} else {
|
|
std::invoke(std::forward<_Func>(__f), __union_.__val_);
|
|
return expected<_Up, _Err>();
|
|
}
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
|
|
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), __union_.__val_);
|
|
} else {
|
|
std::invoke(std::forward<_Func>(__f), __union_.__val_);
|
|
return expected<_Up, _Err>();
|
|
}
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Err, _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
|
|
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(__union_.__val_));
|
|
} else {
|
|
std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
|
|
return expected<_Up, _Err>();
|
|
}
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
|
|
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(__union_.__val_));
|
|
} else {
|
|
std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
|
|
return expected<_Up, _Err>();
|
|
}
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, _Tp&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>;
|
|
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, __union_.__val_);
|
|
}
|
|
return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, const _Tp&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>;
|
|
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, __union_.__val_);
|
|
}
|
|
return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, _Tp&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>;
|
|
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(__union_.__val_));
|
|
}
|
|
return expected<_Tp, _Gp>(
|
|
__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
|
|
}
|
|
|
|
template <class _Func>
|
|
requires is_constructible_v<_Tp, const _Tp&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>;
|
|
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(__union_.__val_));
|
|
}
|
|
return expected<_Tp, _Gp>(
|
|
__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
|
|
}
|
|
|
|
// [expected.object.eq], equality operators
|
|
template <class _T2, class _E2>
|
|
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 <class _T2>
|
|
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
|
|
return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v);
|
|
}
|
|
|
|
template <class _E2>
|
|
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
|
|
return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error());
|
|
}
|
|
|
|
private:
|
|
template <class _ValueType, class _ErrorType>
|
|
union __union_t {
|
|
template <class... _Args>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
|
|
: __val_(std::forward<_Args>(__args)...) {}
|
|
|
|
template <class... _Args>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
|
: __unex_(std::forward<_Args>(__args)...) {}
|
|
|
|
template <class _Func, class... _Args>
|
|
_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 <class _Func, class... _Args>
|
|
_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 <class _Union>
|
|
_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 <class _ValueType, class _ErrorType>
|
|
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 <class... _Args>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
|
|
: __val_(std::forward<_Args>(__args)...) {}
|
|
|
|
template <class... _Args>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
|
: __unex_(std::forward<_Args>(__args)...) {}
|
|
|
|
template <class _Func, class... _Args>
|
|
_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 <class _Func, class... _Args>
|
|
_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 <class _Union>
|
|
_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 <class _Tp, class _Err>
|
|
requires is_void_v<_Tp>
|
|
class expected<_Tp, _Err> {
|
|
static_assert(__valid_std_unexpected<_Err>::value,
|
|
"[expected.void.general] A program that instantiates expected<T, E> with a E that is not a "
|
|
"valid argument for unexpected<E> is ill-formed");
|
|
|
|
template <class, class>
|
|
friend class expected;
|
|
|
|
template <class _Up, class _OtherErr, class _OtherErrQual>
|
|
using __can_convert =
|
|
_And< is_void<_Up>,
|
|
is_constructible<_Err, _OtherErrQual>,
|
|
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
|
|
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
|
|
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
|
|
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>;
|
|
|
|
public:
|
|
using value_type = _Tp;
|
|
using error_type = _Err;
|
|
using unexpected_type = unexpected<_Err>;
|
|
|
|
template <class _Up>
|
|
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 <class _Up, class _OtherErr>
|
|
requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
|
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 <class _Up, class _OtherErr>
|
|
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 <class _OtherErr>
|
|
requires is_constructible_v<_Err, const _OtherErr&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected(
|
|
const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
|
: __union_(std::unexpect, __unex.error()), __has_val_(false) {}
|
|
|
|
template <class _OtherErr>
|
|
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 <class... _Args>
|
|
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 <class _Up, class... _Args>
|
|
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 <class _Func>
|
|
_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 <class _Func, class... _Args>
|
|
_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 <class _OtherErr>
|
|
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 <class _OtherErr>
|
|
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 <class _Up = _Err>
|
|
_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 <class _Up = _Err>
|
|
_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 <class _Func>
|
|
requires is_constructible_v<_Err, _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func>>;
|
|
static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
|
|
static_assert(
|
|
is_same_v<typename _Up::error_type, _Err>, "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 <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func>>;
|
|
static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
|
|
static_assert(
|
|
is_same_v<typename _Up::error_type, _Err>, "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 <class _Func>
|
|
requires is_constructible_v<_Err, _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func>>;
|
|
static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
|
|
static_assert(
|
|
is_same_v<typename _Up::error_type, _Err>, "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 <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
|
|
using _Up = remove_cvref_t<invoke_result_t<_Func>>;
|
|
static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
|
|
static_assert(
|
|
is_same_v<typename _Up::error_type, _Err>, "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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>;
|
|
static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Gp::value_type, _Tp>,
|
|
"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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>;
|
|
static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
|
|
static_assert(is_same_v<typename _Gp::value_type, _Tp>,
|
|
"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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>;
|
|
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<typename _Gp::value_type, _Tp>,
|
|
"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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& {
|
|
using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>;
|
|
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<typename _Gp::value_type, _Tp>,
|
|
"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 <class _Func>
|
|
requires is_constructible_v<_Err, _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func>>;
|
|
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 <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func>>;
|
|
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 <class _Func>
|
|
requires is_constructible_v<_Err, _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func>>;
|
|
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 <class _Func>
|
|
requires is_constructible_v<_Err, const _Err&&>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
|
|
using _Up = remove_cv_t<invoke_result_t<_Func>>;
|
|
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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>;
|
|
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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>;
|
|
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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>;
|
|
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 <class _Func>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& {
|
|
using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>;
|
|
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 <class _T2, class _E2>
|
|
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<bool>(__x.__union_.__unex_ == __y.__union_.__unex_);
|
|
}
|
|
}
|
|
|
|
template <class _E2>
|
|
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
|
|
return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error());
|
|
}
|
|
|
|
private:
|
|
struct __empty_t {};
|
|
|
|
template <class _ErrorType>
|
|
union __union_t {
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
|
|
|
template <class... _Args>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
|
: __unex_(std::forward<_Args>(__args)...) {}
|
|
|
|
template <class _Func, class... _Args>
|
|
_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 <class _Union>
|
|
_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 <class _ErrorType>
|
|
requires is_trivially_move_constructible_v<_ErrorType>
|
|
union __union_t<_ErrorType> {
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
|
|
|
|
template <class... _Args>
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
|
: __unex_(std::forward<_Args>(__args)...) {}
|
|
|
|
template <class _Func, class... _Args>
|
|
_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 <class _Union>
|
|
_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
|