123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242 |
- // <expected> -*- C++ -*-
- // Copyright The GNU Toolchain Authors
- //
- // This file is part of the GNU ISO C++ Library. This library is free
- // software; you can redistribute it and/or modify it under the
- // terms of the GNU General Public License as published by the
- // Free Software Foundation; either version 3, or (at your option)
- // any later version.
- // This library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- // Under Section 7 of GPL version 3, you are granted additional
- // permissions described in the GCC Runtime Library Exception, version
- // 3.1, as published by the Free Software Foundation.
- // You should have received a copy of the GNU General Public License and
- // a copy of the GCC Runtime Library Exception along with this program;
- // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- // <http://www.gnu.org/licenses/>.
- /** @file include/expected
- * This is a Standard C++ Library header.
- */
- #ifndef _GLIBCXX_EXPECTED
- #define _GLIBCXX_EXPECTED
- #pragma GCC system_header
- #if __cplusplus > 202002L && __cpp_concepts >= 202002L
- #include <initializer_list>
- #include <bits/exception.h> // exception
- #include <bits/stl_construct.h> // construct_at
- #include <bits/utility.h> // in_place_t
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- /**
- * @defgroup expected_values Expected values
- * @addtogroup utilities
- * @since C++23
- * @{
- */
- #define __cpp_lib_expected 202202L
- /// Discriminated union that holds an expected value or an error value.
- /**
- * @since C++23
- */
- template<typename _Tp, typename _Er>
- class expected;
- /// Wrapper type used to pass an error value to a `std::expected`.
- /**
- * @since C++23
- */
- template<typename _Er>
- class unexpected;
- /// Exception thrown by std::expected when the value() is not present.
- /**
- * @since C++23
- */
- template<typename _Er>
- class bad_expected_access;
- template<>
- class bad_expected_access<void> : public exception
- {
- protected:
- bad_expected_access() noexcept { }
- bad_expected_access(const bad_expected_access&) = default;
- bad_expected_access(bad_expected_access&&) = default;
- bad_expected_access& operator=(const bad_expected_access&) = default;
- bad_expected_access& operator=(bad_expected_access&&) = default;
- ~bad_expected_access() = default;
- public:
- [[nodiscard]]
- const char*
- what() const noexcept override
- { return "bad access to std::expected without expected value"; }
- };
- template<typename _Er>
- class bad_expected_access : public bad_expected_access<void> {
- public:
- explicit
- bad_expected_access(_Er __e) : _M_unex(std::move(__e)) { }
- // XXX const char* what() const noexcept override;
- [[nodiscard]]
- _Er&
- error() & noexcept
- { return _M_unex; }
- [[nodiscard]]
- const _Er&
- error() const & noexcept
- { return _M_unex; }
- [[nodiscard]]
- _Er&&
- error() && noexcept
- { return std::move(_M_unex); }
- [[nodiscard]]
- const _Er&&
- error() const && noexcept
- { return std::move(_M_unex); }
- private:
- _Er _M_unex;
- };
- /// Tag type for constructing unexpected values in a std::expected
- /**
- * @since C++23
- */
- struct unexpect_t
- {
- explicit unexpect_t() = default;
- };
- /// Tag for constructing unexpected values in a std::expected
- /**
- * @since C++23
- */
- inline constexpr unexpect_t unexpect{};
- /// @cond undoc
- namespace __expected
- {
- template<typename _Tp>
- constexpr bool __is_expected = false;
- template<typename _Tp, typename _Er>
- constexpr bool __is_expected<expected<_Tp, _Er>> = true;
- template<typename _Tp>
- constexpr bool __is_unexpected = false;
- template<typename _Tp>
- constexpr bool __is_unexpected<unexpected<_Tp>> = true;
- template<typename _Er>
- concept __can_be_unexpected
- = is_object_v<_Er> && (!is_array_v<_Er>)
- && (!__expected::__is_unexpected<_Er>)
- && (!is_const_v<_Er>) && (!is_volatile_v<_Er>);
- }
- /// @endcond
- template<typename _Er>
- class unexpected
- {
- static_assert( __expected::__can_be_unexpected<_Er> );
- public:
- constexpr unexpected(const unexpected&) = default;
- constexpr unexpected(unexpected&&) = default;
- template<typename _Err = _Er>
- requires (!is_same_v<remove_cvref_t<_Err>, unexpected>)
- && (!is_same_v<remove_cvref_t<_Err>, in_place_t>)
- && is_constructible_v<_Er, _Err>
- constexpr explicit
- unexpected(_Err&& __e)
- noexcept(is_nothrow_constructible_v<_Er, _Err>)
- : _M_unex(std::forward<_Err>(__e))
- { }
- template<typename... _Args>
- requires is_constructible_v<_Er, _Args...>
- constexpr explicit
- unexpected(in_place_t, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Er, _Args...>)
- : _M_unex(std::forward<_Args>(__args)...)
- { }
- template<typename _Up, typename... _Args>
- requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
- constexpr explicit
- unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
- _Args...>)
- : _M_unex(__il, std::forward<_Args>(__args)...)
- { }
- constexpr unexpected& operator=(const unexpected&) = default;
- constexpr unexpected& operator=(unexpected&&) = default;
- [[nodiscard]]
- constexpr const _Er&
- error() const & noexcept { return _M_unex; }
- [[nodiscard]]
- constexpr _Er&
- error() & noexcept { return _M_unex; }
- [[nodiscard]]
- constexpr const _Er&&
- error() const && noexcept { return std::move(_M_unex); }
- [[nodiscard]]
- constexpr _Er&&
- error() && noexcept { return std::move(_M_unex); }
- constexpr void
- swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Er>)
- {
- static_assert( is_swappable_v<_Er> );
- using std::swap;
- swap(_M_unex, __other._M_unex);
- }
- template<typename _Err>
- [[nodiscard]]
- friend constexpr bool
- operator==(const unexpected& __x, const unexpected<_Err>& __y)
- { return __x._M_unex == __y.error(); }
- friend constexpr void
- swap(unexpected& __x, unexpected& __y)
- noexcept(noexcept(__x.swap(__y)))
- requires requires {__x.swap(__y);}
- { __x.swap(__y); }
- private:
- _Er _M_unex;
- };
- template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
- /// @cond undoc
- namespace __expected
- {
- template<typename _Tp>
- struct _Guard
- {
- static_assert( is_nothrow_move_constructible_v<_Tp> );
- constexpr explicit
- _Guard(_Tp& __x)
- : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow
- { std::destroy_at(_M_guarded); }
- constexpr
- ~_Guard()
- {
- if (_M_guarded) [[unlikely]]
- std::construct_at(_M_guarded, std::move(_M_tmp));
- }
- _Guard(const _Guard&) = delete;
- _Guard& operator=(const _Guard&) = delete;
- constexpr _Tp&&
- release() noexcept
- {
- _M_guarded = nullptr;
- return std::move(_M_tmp);
- }
- private:
- _Tp* _M_guarded;
- _Tp _M_tmp;
- };
- // reinit-expected helper from [expected.object.assign]
- template<typename _Tp, typename _Up, typename _Vp>
- constexpr void
- __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg)
- noexcept(is_nothrow_constructible_v<_Tp, _Vp>)
- {
- if constexpr (is_nothrow_constructible_v<_Tp, _Vp>)
- {
- std::destroy_at(__oldval);
- std::construct_at(__newval, std::forward<_Vp>(__arg));
- }
- else if constexpr (is_nothrow_move_constructible_v<_Tp>)
- {
- _Tp __tmp(std::forward<_Vp>(__arg)); // might throw
- std::destroy_at(__oldval);
- std::construct_at(__newval, std::move(__tmp));
- }
- else
- {
- _Guard<_Up> __guard(*__oldval);
- std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw
- __guard.release();
- }
- }
- }
- /// @endcond
- template<typename _Tp, typename _Er>
- class expected
- {
- static_assert( ! is_reference_v<_Tp> );
- static_assert( ! is_function_v<_Tp> );
- static_assert( ! is_same_v<remove_cv_t<_Tp>, in_place_t> );
- static_assert( ! is_same_v<remove_cv_t<_Tp>, unexpect_t> );
- static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
- static_assert( __expected::__can_be_unexpected<_Er> );
- template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
- static constexpr bool __cons_from_expected
- = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
- is_constructible<_Tp, expected<_Up, _Err>>,
- is_constructible<_Tp, const expected<_Up, _Err>&>,
- is_constructible<_Tp, const expected<_Up, _Err>>,
- is_convertible<expected<_Up, _Err>&, _Tp>,
- is_convertible<expected<_Up, _Err>, _Tp>,
- is_convertible<const expected<_Up, _Err>&, _Tp>,
- is_convertible<const expected<_Up, _Err>, _Tp>,
- is_constructible<_Unex, expected<_Up, _Err>&>,
- is_constructible<_Unex, expected<_Up, _Err>>,
- is_constructible<_Unex, const expected<_Up, _Err>&>,
- is_constructible<_Unex, const expected<_Up, _Err>>
- >;
- template<typename _Up, typename _Err>
- constexpr static bool __explicit_conv
- = __or_v<__not_<is_convertible<_Up, _Tp>>,
- __not_<is_convertible<_Err, _Er>>
- >;
- public:
- using value_type = _Tp;
- using error_type = _Er;
- using unexpected_type = unexpected<_Er>;
- template<typename _Up>
- using rebind = expected<_Up, error_type>;
- constexpr
- expected()
- noexcept(is_nothrow_default_constructible_v<_Tp>)
- requires is_default_constructible_v<_Tp>
- : _M_val(), _M_has_value(true)
- { }
- expected(const expected&) = default;
- constexpr
- expected(const expected& __x)
- noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
- is_nothrow_copy_constructible<_Er>>)
- requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er>
- && (!is_trivially_copy_constructible_v<_Tp>
- || !is_trivially_copy_constructible_v<_Er>)
- : _M_invalid(), _M_has_value(__x._M_has_value)
- {
- if (_M_has_value)
- std::construct_at(__builtin_addressof(_M_val), __x._M_val);
- else
- std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
- }
- expected(expected&&) = default;
- constexpr
- expected(expected&& __x)
- noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
- is_nothrow_move_constructible<_Er>>)
- requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er>
- && (!is_trivially_move_constructible_v<_Tp>
- || !is_trivially_move_constructible_v<_Er>)
- : _M_invalid(), _M_has_value(__x._M_has_value)
- {
- if (_M_has_value)
- std::construct_at(__builtin_addressof(_M_val),
- std::move(__x)._M_val);
- else
- std::construct_at(__builtin_addressof(_M_unex),
- std::move(__x)._M_unex);
- }
- template<typename _Up, typename _Gr>
- requires is_constructible_v<_Tp, const _Up&>
- && is_constructible_v<_Er, const _Gr&>
- && (!__cons_from_expected<_Up, _Gr>)
- constexpr explicit(__explicit_conv<const _Up&, const _Gr&>)
- expected(const expected<_Up, _Gr>& __x)
- noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
- is_nothrow_constructible<_Er, const _Gr&>>)
- : _M_invalid(), _M_has_value(__x._M_has_value)
- {
- if (_M_has_value)
- std::construct_at(__builtin_addressof(_M_val), __x._M_val);
- else
- std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
- }
- template<typename _Up, typename _Gr>
- requires is_constructible_v<_Tp, _Up>
- && is_constructible_v<_Er, _Gr>
- && (!__cons_from_expected<_Up, _Gr>)
- constexpr explicit(__explicit_conv<_Up, _Gr>)
- expected(expected<_Up, _Gr>&& __x)
- noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
- is_nothrow_constructible<_Er, _Gr>>)
- : _M_invalid(), _M_has_value(__x._M_has_value)
- {
- if (_M_has_value)
- std::construct_at(__builtin_addressof(_M_val),
- std::move(__x)._M_val);
- else
- std::construct_at(__builtin_addressof(_M_unex),
- std::move(__x)._M_unex);
- }
- template<typename _Up = _Tp>
- requires (!is_same_v<remove_cvref_t<_Up>, expected>)
- && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
- && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
- && is_constructible_v<_Tp, _Up>
- constexpr explicit(!is_convertible_v<_Up, _Tp>)
- expected(_Up&& __v)
- noexcept(is_nothrow_constructible_v<_Tp, _Up>)
- : _M_val(std::forward<_Up>(__v)), _M_has_value(true)
- { }
- template<typename _Gr = _Er>
- requires is_constructible_v<_Er, const _Gr&>
- constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
- expected(const unexpected<_Gr>& __u)
- noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
- : _M_unex(__u.error()), _M_has_value(false)
- { }
- template<typename _Gr = _Er>
- requires is_constructible_v<_Er, _Gr>
- constexpr explicit(!is_convertible_v<_Gr, _Er>)
- expected(unexpected<_Gr>&& __u)
- noexcept(is_nothrow_constructible_v<_Er, _Gr>)
- : _M_unex(std::move(__u).error()), _M_has_value(false)
- { }
- template<typename... _Args>
- requires is_constructible_v<_Tp, _Args...>
- constexpr explicit
- expected(in_place_t, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
- : _M_val(std::forward<_Args>(__args)...), _M_has_value(true)
- { }
- template<typename _Up, typename... _Args>
- requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
- constexpr explicit
- expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
- _Args...>)
- : _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true)
- { }
- template<typename... _Args>
- requires is_constructible_v<_Er, _Args...>
- constexpr explicit
- expected(unexpect_t, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Er, _Args...>)
- : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
- { }
- template<typename _Up, typename... _Args>
- requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
- constexpr explicit
- expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
- _Args...>)
- : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
- { }
- constexpr ~expected() = default;
- constexpr ~expected()
- requires (!is_trivially_destructible_v<_Tp>)
- || (!is_trivially_destructible_v<_Er>)
- {
- if (_M_has_value)
- std::destroy_at(__builtin_addressof(_M_val));
- else
- std::destroy_at(__builtin_addressof(_M_unex));
- }
- // assignment
- expected& operator=(const expected&) = delete;
- constexpr expected&
- operator=(const expected& __x)
- noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
- is_nothrow_copy_constructible<_Er>,
- is_nothrow_copy_assignable<_Tp>,
- is_nothrow_copy_assignable<_Er>>)
- requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp>
- && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er>
- && (is_nothrow_move_constructible_v<_Tp>
- || is_nothrow_move_constructible_v<_Er>)
- {
- if (__x._M_has_value)
- this->_M_assign_val(__x._M_val);
- else
- this->_M_assign_unex(__x._M_unex);
- return *this;
- }
- constexpr expected&
- operator=(expected&& __x)
- noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
- is_nothrow_move_constructible<_Er>,
- is_nothrow_move_assignable<_Tp>,
- is_nothrow_move_assignable<_Er>>)
- requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp>
- && is_move_assignable_v<_Er> && is_move_constructible_v<_Er>
- && (is_nothrow_move_constructible_v<_Tp>
- || is_nothrow_move_constructible_v<_Er>)
- {
- if (__x._M_has_value)
- _M_assign_val(std::move(__x._M_val));
- else
- _M_assign_unex(std::move(__x._M_unex));
- return *this;
- }
- template<typename _Up = _Tp>
- requires (!is_same_v<expected, remove_cvref_t<_Up>>)
- && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
- && 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<_Er>)
- constexpr expected&
- operator=(_Up&& __v)
- {
- _M_assign_val(std::forward<_Up>(__v));
- return *this;
- }
- template<typename _Gr>
- requires is_constructible_v<_Er, const _Gr&>
- && is_assignable_v<_Er&, const _Gr&>
- && (is_nothrow_constructible_v<_Er, const _Gr&>
- || is_nothrow_move_constructible_v<_Tp>
- || is_nothrow_move_constructible_v<_Er>)
- constexpr expected&
- operator=(const unexpected<_Gr>& __e)
- {
- _M_assign_unex(__e.error());
- return *this;
- }
- template<typename _Gr>
- requires is_constructible_v<_Er, _Gr>
- && is_assignable_v<_Er&, _Gr>
- && (is_nothrow_constructible_v<_Er, _Gr>
- || is_nothrow_move_constructible_v<_Tp>
- || is_nothrow_move_constructible_v<_Er>)
- constexpr expected&
- operator=(unexpected<_Gr>&& __e)
- {
- _M_assign_unex(std::move(__e).error());
- return *this;
- }
- // modifiers
- template<typename... _Args>
- requires is_nothrow_constructible_v<_Tp, _Args...>
- constexpr _Tp&
- emplace(_Args&&... __args) noexcept
- {
- if (_M_has_value)
- std::destroy_at(__builtin_addressof(_M_val));
- else
- {
- std::destroy_at(__builtin_addressof(_M_unex));
- _M_has_value = true;
- }
- std::construct_at(__builtin_addressof(_M_val),
- std::forward<_Args>(__args)...);
- return _M_val;
- }
- template<typename _Up, typename... _Args>
- requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
- _Args...>
- constexpr _Tp&
- emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept
- {
- if (_M_has_value)
- std::destroy_at(__builtin_addressof(_M_val));
- else
- {
- std::destroy_at(__builtin_addressof(_M_unex));
- _M_has_value = true;
- }
- std::construct_at(__builtin_addressof(_M_val),
- __il, std::forward<_Args>(__args)...);
- return _M_val;
- }
- // swap
- constexpr void
- swap(expected& __x)
- noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
- is_nothrow_move_constructible<_Er>,
- is_nothrow_swappable<_Tp&>,
- is_nothrow_swappable<_Er&>>)
- requires is_swappable_v<_Tp> && is_swappable_v<_Er>
- && is_move_constructible_v<_Tp>
- && is_move_constructible_v<_Er>
- && (is_nothrow_move_constructible_v<_Tp>
- || is_nothrow_move_constructible_v<_Er>)
- {
- if (_M_has_value)
- {
- if (__x._M_has_value)
- {
- using std::swap;
- swap(_M_val, __x._M_val);
- }
- else
- this->_M_swap_val_unex(__x);
- }
- else
- {
- if (__x._M_has_value)
- __x._M_swap_val_unex(*this);
- else
- {
- using std::swap;
- swap(_M_unex, __x._M_unex);
- }
- }
- }
- // observers
- [[nodiscard]]
- constexpr const _Tp*
- operator->() const noexcept
- {
- __glibcxx_assert(_M_has_value);
- return __builtin_addressof(_M_val);
- }
- [[nodiscard]]
- constexpr _Tp*
- operator->() noexcept
- {
- __glibcxx_assert(_M_has_value);
- return __builtin_addressof(_M_val);
- }
- [[nodiscard]]
- constexpr const _Tp&
- operator*() const & noexcept
- {
- __glibcxx_assert(_M_has_value);
- return _M_val;
- }
- [[nodiscard]]
- constexpr _Tp&
- operator*() & noexcept
- {
- __glibcxx_assert(_M_has_value);
- return _M_val;
- }
- [[nodiscard]]
- constexpr const _Tp&&
- operator*() const && noexcept
- {
- __glibcxx_assert(_M_has_value);
- return std::move(_M_val);
- }
- [[nodiscard]]
- constexpr _Tp&&
- operator*() && noexcept
- {
- __glibcxx_assert(_M_has_value);
- return std::move(_M_val);
- }
- [[nodiscard]]
- constexpr explicit
- operator bool() const noexcept { return _M_has_value; }
- [[nodiscard]]
- constexpr bool has_value() const noexcept { return _M_has_value; }
- constexpr const _Tp&
- value() const &
- {
- if (_M_has_value) [[likely]]
- return _M_val;
- _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
- }
- constexpr _Tp&
- value() &
- {
- if (_M_has_value) [[likely]]
- return _M_val;
- _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
- }
- constexpr const _Tp&&
- value() const &&
- {
- if (_M_has_value) [[likely]]
- return std::move(_M_val);
- _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
- std::move(_M_unex)));
- }
- constexpr _Tp&&
- value() &&
- {
- if (_M_has_value) [[likely]]
- return std::move(_M_val);
- _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
- std::move(_M_unex)));
- }
- constexpr const _Er&
- error() const & noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return _M_unex;
- }
- constexpr _Er&
- error() & noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return _M_unex;
- }
- constexpr const _Er&&
- error() const && noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return std::move(_M_unex);
- }
- constexpr _Er&&
- error() && noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return std::move(_M_unex);
- }
- template<typename _Up>
- constexpr _Tp
- value_or(_Up&& __v) const &
- noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
- is_nothrow_convertible<_Up, _Tp>>)
- {
- static_assert( is_copy_constructible_v<_Tp> );
- static_assert( is_convertible_v<_Up, _Tp> );
- if (_M_has_value)
- return _M_val;
- return static_cast<_Tp>(std::forward<_Up>(__v));
- }
- template<typename _Up>
- constexpr _Tp
- value_or(_Up&& __v) &&
- noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
- is_nothrow_convertible<_Up, _Tp>>)
- {
- static_assert( is_move_constructible_v<_Tp> );
- static_assert( is_convertible_v<_Up, _Tp> );
- if (_M_has_value)
- return std::move(_M_val);
- return static_cast<_Tp>(std::forward<_Up>(__v));
- }
- // equality operators
- template<typename _Up, typename _Er2>
- requires (!is_void_v<_Up>)
- friend constexpr bool
- operator==(const expected& __x, const expected<_Up, _Er2>& __y)
- noexcept(noexcept(bool(*__x == *__y))
- && noexcept(bool(__x.error() == __y.error())))
- {
- if (__x.has_value())
- return __y.has_value() && bool(*__x == *__y);
- else
- return !__y.has_value() && bool(__x.error() == __y.error());
- }
- template<typename _Up>
- friend constexpr bool
- operator==(const expected& __x, const _Up& __v)
- noexcept(noexcept(bool(*__x == __v)))
- { return __x.has_value() && bool(*__x == __v); }
- template<typename _Er2>
- friend constexpr bool
- operator==(const expected& __x, const unexpected<_Er2>& __e)
- noexcept(noexcept(bool(__x.error() == __e.error())))
- { return !__x.has_value() && bool(__x.error() == __e.error()); }
- friend constexpr void
- swap(expected& __x, expected& __y)
- noexcept(noexcept(__x.swap(__y)))
- requires requires {__x.swap(__y);}
- { __x.swap(__y); }
- private:
- template<typename, typename> friend class expected;
- template<typename _Vp>
- constexpr void
- _M_assign_val(_Vp&& __v)
- {
- if (_M_has_value)
- _M_val = std::forward<_Vp>(__v);
- else
- {
- __expected::__reinit(__builtin_addressof(_M_val),
- __builtin_addressof(_M_unex),
- std::forward<_Vp>(__v));
- _M_has_value = true;
- }
- }
- template<typename _Vp>
- constexpr void
- _M_assign_unex(_Vp&& __v)
- {
- if (_M_has_value)
- {
- __expected::__reinit(__builtin_addressof(_M_unex),
- __builtin_addressof(_M_val),
- std::forward<_Vp>(__v));
- _M_has_value = false;
- }
- else
- _M_unex = std::forward<_Vp>(__v);
- }
- // Swap two expected objects when only one has a value.
- // Precondition: this->_M_has_value && !__rhs._M_has_value
- constexpr void
- _M_swap_val_unex(expected& __rhs)
- noexcept(__and_v<is_nothrow_move_constructible<_Er>,
- is_nothrow_move_constructible<_Tp>>)
- {
- if constexpr (is_nothrow_move_constructible_v<_Er>)
- {
- __expected::_Guard<_Er> __guard(__rhs._M_unex);
- std::construct_at(__builtin_addressof(__rhs._M_val),
- std::move(_M_val)); // might throw
- __rhs._M_has_value = true;
- std::destroy_at(__builtin_addressof(_M_val));
- std::construct_at(__builtin_addressof(_M_unex),
- __guard.release());
- _M_has_value = false;
- }
- else
- {
- __expected::_Guard<_Tp> __guard(__rhs._M_val);
- std::construct_at(__builtin_addressof(_M_unex),
- std::move(__rhs._M_unex)); // might throw
- _M_has_value = false;
- std::destroy_at(__builtin_addressof(__rhs._M_unex));
- std::construct_at(__builtin_addressof(__rhs._M_val),
- __guard.release());
- __rhs._M_has_value = true;
- }
- }
- union {
- struct { } _M_invalid;
- _Tp _M_val;
- _Er _M_unex;
- };
- bool _M_has_value;
- };
- // Partial specialization for std::expected<cv void, E>
- template<typename _Tp, typename _Er> requires is_void_v<_Tp>
- class expected<_Tp, _Er>
- {
- static_assert( __expected::__can_be_unexpected<_Er> );
- template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
- static constexpr bool __cons_from_expected
- = __or_v<is_constructible<_Unex, expected<_Up, _Err>&>,
- is_constructible<_Unex, expected<_Up, _Err>>,
- is_constructible<_Unex, const expected<_Up, _Err>&>,
- is_constructible<_Unex, const expected<_Up, _Err>>
- >;
- public:
- using value_type = _Tp;
- using error_type = _Er;
- using unexpected_type = unexpected<_Er>;
- template<typename _Up>
- using rebind = expected<_Up, error_type>;
- constexpr
- expected() noexcept
- : _M_void(), _M_has_value(true)
- { }
- expected(const expected&) = default;
- constexpr
- expected(const expected& __x)
- noexcept(is_nothrow_copy_constructible_v<_Er>)
- requires is_copy_constructible_v<_Er>
- && (!is_trivially_copy_constructible_v<_Er>)
- : _M_void(), _M_has_value(__x._M_has_value)
- {
- if (!_M_has_value)
- std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
- }
- expected(expected&&) = default;
- constexpr
- expected(expected&& __x)
- noexcept(is_nothrow_move_constructible_v<_Er>)
- requires is_move_constructible_v<_Er>
- && (!is_trivially_move_constructible_v<_Er>)
- : _M_void(), _M_has_value(__x._M_has_value)
- {
- if (!_M_has_value)
- std::construct_at(__builtin_addressof(_M_unex),
- std::move(__x)._M_unex);
- }
- template<typename _Up, typename _Gr>
- requires is_void_v<_Up>
- && is_constructible_v<_Er, const _Gr&>
- && (!__cons_from_expected<_Up, _Gr>)
- constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
- expected(const expected<_Up, _Gr>& __x)
- noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
- : _M_void(), _M_has_value(__x._M_has_value)
- {
- if (!_M_has_value)
- std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
- }
- template<typename _Up, typename _Gr>
- requires is_void_v<_Up>
- && is_constructible_v<_Er, _Gr>
- && (!__cons_from_expected<_Up, _Gr>)
- constexpr explicit(!is_convertible_v<_Gr, _Er>)
- expected(expected<_Up, _Gr>&& __x)
- noexcept(is_nothrow_constructible_v<_Er, _Gr>)
- : _M_void(), _M_has_value(__x._M_has_value)
- {
- if (!_M_has_value)
- std::construct_at(__builtin_addressof(_M_unex),
- std::move(__x)._M_unex);
- }
- template<typename _Gr = _Er>
- requires is_constructible_v<_Er, const _Gr&>
- constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
- expected(const unexpected<_Gr>& __u)
- noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
- : _M_unex(__u.error()), _M_has_value(false)
- { }
- template<typename _Gr = _Er>
- requires is_constructible_v<_Er, _Gr>
- constexpr explicit(!is_convertible_v<_Gr, _Er>)
- expected(unexpected<_Gr>&& __u)
- noexcept(is_nothrow_constructible_v<_Er, _Gr>)
- : _M_unex(std::move(__u).error()), _M_has_value(false)
- { }
- template<typename... _Args>
- constexpr explicit
- expected(in_place_t) noexcept
- : expected()
- { }
- template<typename... _Args>
- requires is_constructible_v<_Er, _Args...>
- constexpr explicit
- expected(unexpect_t, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Er, _Args...>)
- : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
- { }
- template<typename _Up, typename... _Args>
- requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
- constexpr explicit
- expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
- _Args...>)
- : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
- { }
- constexpr ~expected() = default;
- constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
- {
- if (!_M_has_value)
- std::destroy_at(__builtin_addressof(_M_unex));
- }
- // assignment
- expected& operator=(const expected&) = delete;
- constexpr expected&
- operator=(const expected& __x)
- noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
- is_nothrow_copy_assignable<_Er>>)
- requires is_copy_constructible_v<_Er>
- && is_copy_assignable_v<_Er>
- {
- if (__x._M_has_value)
- emplace();
- else
- _M_assign_unex(__x._M_unex);
- return *this;
- }
- constexpr expected&
- operator=(expected&& __x)
- noexcept(__and_v<is_nothrow_move_constructible<_Er>,
- is_nothrow_move_assignable<_Er>>)
- requires is_move_constructible_v<_Er>
- && is_move_assignable_v<_Er>
- {
- if (__x._M_has_value)
- emplace();
- else
- _M_assign_unex(std::move(__x._M_unex));
- return *this;
- }
- template<typename _Gr>
- requires is_constructible_v<_Er, const _Gr&>
- && is_assignable_v<_Er&, const _Gr&>
- constexpr expected&
- operator=(const unexpected<_Gr>& __e)
- {
- _M_assign_unex(__e.error());
- return *this;
- }
- template<typename _Gr>
- requires is_constructible_v<_Er, _Gr>
- && is_assignable_v<_Er&, _Gr>
- constexpr expected&
- operator=(unexpected<_Gr>&& __e)
- {
- _M_assign_unex(std::move(__e.error()));
- return *this;
- }
- // modifiers
- constexpr void
- emplace() noexcept
- {
- if (!_M_has_value)
- {
- std::destroy_at(__builtin_addressof(_M_unex));
- _M_has_value = true;
- }
- }
- // swap
- constexpr void
- swap(expected& __x)
- noexcept(__and_v<is_nothrow_swappable<_Er&>,
- is_nothrow_move_constructible<_Er>>)
- requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
- {
- if (_M_has_value)
- {
- if (!__x._M_has_value)
- {
- std::construct_at(__builtin_addressof(_M_unex),
- std::move(__x._M_unex)); // might throw
- std::destroy_at(__builtin_addressof(__x._M_unex));
- _M_has_value = false;
- __x._M_has_value = true;
- }
- }
- else
- {
- if (__x._M_has_value)
- {
- std::construct_at(__builtin_addressof(__x._M_unex),
- std::move(_M_unex)); // might throw
- std::destroy_at(__builtin_addressof(_M_unex));
- _M_has_value = true;
- __x._M_has_value = false;
- }
- else
- {
- using std::swap;
- swap(_M_unex, __x._M_unex);
- }
- }
- }
- // observers
- [[nodiscard]]
- constexpr explicit
- operator bool() const noexcept { return _M_has_value; }
- [[nodiscard]]
- constexpr bool has_value() const noexcept { return _M_has_value; }
- constexpr void
- operator*() const noexcept { __glibcxx_assert(_M_has_value); }
- constexpr void
- value() const&
- {
- if (_M_has_value) [[likely]]
- return;
- _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
- }
- constexpr void
- value() &&
- {
- if (_M_has_value) [[likely]]
- return;
- _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
- }
- constexpr const _Er&
- error() const & noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return _M_unex;
- }
- constexpr _Er&
- error() & noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return _M_unex;
- }
- constexpr const _Er&&
- error() const && noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return std::move(_M_unex);
- }
- constexpr _Er&&
- error() && noexcept
- {
- __glibcxx_assert(!_M_has_value);
- return std::move(_M_unex);
- }
- // equality operators
- template<typename _Up, typename _Er2>
- requires is_void_v<_Up>
- friend constexpr bool
- operator==(const expected& __x, const expected<_Up, _Er2>& __y)
- noexcept(noexcept(bool(__x.error() == __y.error())))
- {
- if (__x.has_value())
- return __y.has_value();
- else
- return !__y.has_value() && bool(__x.error() == __y.error());
- }
- template<typename _Er2>
- friend constexpr bool
- operator==(const expected& __x, const unexpected<_Er2>& __e)
- noexcept(noexcept(bool(__x.error() == __e.error())))
- { return !__x.has_value() && bool(__x.error() == __e.error()); }
- friend constexpr void
- swap(expected& __x, expected& __y)
- noexcept(noexcept(__x.swap(__y)))
- requires requires { __x.swap(__y); }
- { __x.swap(__y); }
- private:
- template<typename, typename> friend class expected;
- template<typename _Vp>
- constexpr void
- _M_assign_unex(_Vp&& __v)
- {
- if (_M_has_value)
- {
- std::construct_at(__builtin_addressof(_M_unex),
- std::forward<_Vp>(__v));
- _M_has_value = false;
- }
- else
- _M_unex = std::forward<_Vp>(__v);
- }
- union {
- struct { } _M_void;
- _Er _M_unex;
- };
- bool _M_has_value;
- };
- /// @}
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
- #endif // C++23
- #endif // _GLIBCXX_EXPECTED
|