| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851 |
- // <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/invoke.h> // __invoke
- #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 202211L
- /// 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 undocumented
- 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 _Fn, typename _Tp>
- using __result = remove_cvref_t<invoke_result_t<_Fn&&, _Tp&&>>;
- template<typename _Fn, typename _Tp>
- using __result_xform = remove_cv_t<invoke_result_t<_Fn&&, _Tp&&>>;
- template<typename _Fn>
- using __result0 = remove_cvref_t<invoke_result_t<_Fn&&>>;
- template<typename _Fn>
- using __result0_xform = remove_cv_t<invoke_result_t<_Fn&&>>;
- 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>);
- // Tag types for in-place construction from an invocation result.
- struct __in_place_inv { };
- struct __unexpect_inv { };
- }
- /// @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>)
- requires 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 is_swappable_v<_Er>
- { __x.swap(__y); }
- private:
- _Er _M_unex;
- };
- template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
- /// @cond undocumented
- 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>>
- >;
- template<typename _Up>
- static constexpr bool __same_val
- = is_same_v<typename _Up::value_type, _Tp>;
- template<typename _Up>
- static constexpr bool __same_err
- = is_same_v<typename _Up::error_type, _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_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_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_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_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;
- const auto& __unex = _M_unex;
- _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(__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));
- }
- template<typename _Gr = _Er>
- constexpr _Er
- error_or(_Gr&& __e) const&
- {
- static_assert( is_copy_constructible_v<_Er> );
- static_assert( is_convertible_v<_Gr, _Er> );
- if (_M_has_value)
- return std::forward<_Gr>(__e);
- return _M_unex;
- }
- template<typename _Gr = _Er>
- constexpr _Er
- error_or(_Gr&& __e) &&
- {
- static_assert( is_move_constructible_v<_Er> );
- static_assert( is_convertible_v<_Gr, _Er> );
- if (_M_has_value)
- return std::forward<_Gr>(__e);
- return std::move(_M_unex);
- }
- // monadic operations
- template<typename _Fn> requires is_constructible_v<_Er, _Er&>
- constexpr auto
- and_then(_Fn&& __f) &
- {
- using _Up = __expected::__result<_Fn, _Tp&>;
- static_assert(__expected::__is_expected<_Up>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected");
- static_assert(is_same_v<typename _Up::error_type, _Er>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected with the same error_type");
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f), _M_val);
- else
- return _Up(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er&>
- constexpr auto
- and_then(_Fn&& __f) const &
- {
- using _Up = __expected::__result<_Fn, const _Tp&>;
- static_assert(__expected::__is_expected<_Up>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected");
- static_assert(is_same_v<typename _Up::error_type, _Er>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected with the same error_type");
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f), _M_val);
- else
- return _Up(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, _Er>
- constexpr auto
- and_then(_Fn&& __f) &&
- {
- using _Up = __expected::__result<_Fn, _Tp&&>;
- static_assert(__expected::__is_expected<_Up>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected");
- static_assert(is_same_v<typename _Up::error_type, _Er>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected with the same error_type");
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f), std::move(_M_val));
- else
- return _Up(unexpect, std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er>
- constexpr auto
- and_then(_Fn&& __f) const &&
- {
- using _Up = __expected::__result<_Fn, const _Tp&&>;
- static_assert(__expected::__is_expected<_Up>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected");
- static_assert(is_same_v<typename _Up::error_type, _Er>,
- "the function passed to std::expected<T, E>::and_then "
- "must return a std::expected with the same error_type");
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f), std::move(_M_val));
- else
- return _Up(unexpect, std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Tp, _Tp&>
- constexpr auto
- or_else(_Fn&& __f) &
- {
- using _Gr = __expected::__result<_Fn, _Er&>;
- static_assert(__expected::__is_expected<_Gr>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected");
- static_assert(is_same_v<typename _Gr::value_type, _Tp>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected with the same value_type");
- if (has_value())
- return _Gr(in_place, _M_val);
- else
- return std::__invoke(std::forward<_Fn>(__f), _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Tp, const _Tp&>
- constexpr auto
- or_else(_Fn&& __f) const &
- {
- using _Gr = __expected::__result<_Fn, const _Er&>;
- static_assert(__expected::__is_expected<_Gr>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected");
- static_assert(is_same_v<typename _Gr::value_type, _Tp>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected with the same value_type");
- if (has_value())
- return _Gr(in_place, _M_val);
- else
- return std::__invoke(std::forward<_Fn>(__f), _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Tp, _Tp>
- constexpr auto
- or_else(_Fn&& __f) &&
- {
- using _Gr = __expected::__result<_Fn, _Er&&>;
- static_assert(__expected::__is_expected<_Gr>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected");
- static_assert(is_same_v<typename _Gr::value_type, _Tp>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected with the same value_type");
- if (has_value())
- return _Gr(in_place, std::move(_M_val));
- else
- return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Tp, const _Tp>
- constexpr auto
- or_else(_Fn&& __f) const &&
- {
- using _Gr = __expected::__result<_Fn, const _Er&&>;
- static_assert(__expected::__is_expected<_Gr>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected");
- static_assert(is_same_v<typename _Gr::value_type, _Tp>,
- "the function passed to std::expected<T, E>::or_else "
- "must return a std::expected with the same value_type");
- if (has_value())
- return _Gr(in_place, std::move(_M_val));
- else
- return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Er, _Er&>
- constexpr auto
- transform(_Fn&& __f) &
- {
- using _Up = __expected::__result_xform<_Fn, _Tp&>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- _M_val);
- });
- else
- return _Res(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er&>
- constexpr auto
- transform(_Fn&& __f) const &
- {
- using _Up = __expected::__result_xform<_Fn, const _Tp&>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- _M_val);
- });
- else
- return _Res(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, _Er>
- constexpr auto
- transform(_Fn&& __f) &&
- {
- using _Up = __expected::__result_xform<_Fn, _Tp>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- std::move(_M_val));
- });
- else
- return _Res(unexpect, std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er>
- constexpr auto
- transform(_Fn&& __f) const &&
- {
- using _Up = __expected::__result_xform<_Fn, const _Tp>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- std::move(_M_val));
- });
- else
- return _Res(unexpect, std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Tp, _Tp&>
- constexpr auto
- transform_error(_Fn&& __f) &
- {
- using _Gr = __expected::__result_xform<_Fn, _Er&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res(in_place, _M_val);
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- _M_unex);
- });
- }
- template<typename _Fn> requires is_constructible_v<_Tp, const _Tp&>
- constexpr auto
- transform_error(_Fn&& __f) const &
- {
- using _Gr = __expected::__result_xform<_Fn, const _Er&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res(in_place, _M_val);
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- _M_unex);
- });
- }
- template<typename _Fn> requires is_constructible_v<_Tp, _Tp>
- constexpr auto
- transform_error(_Fn&& __f) &&
- {
- using _Gr = __expected::__result_xform<_Fn, _Er&&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res(in_place, std::move(_M_val));
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- std::move(_M_unex));
- });
- }
- template<typename _Fn> requires is_constructible_v<_Tp, const _Tp>
- constexpr auto
- transform_error(_Fn&& __f) const &&
- {
- using _Gr = __expected::__result_xform<_Fn, const _Er&&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res(in_place, std::move(_M_val));
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- 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)
- // FIXME: 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)
- // FIXME: 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)
- // FIXME: 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(_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;
- }
- }
- using __in_place_inv = __expected::__in_place_inv;
- using __unexpect_inv = __expected::__unexpect_inv;
- template<typename _Fn>
- explicit constexpr
- expected(__in_place_inv, _Fn&& __fn)
- : _M_val(std::forward<_Fn>(__fn)()), _M_has_value(true)
- { }
- template<typename _Fn>
- explicit constexpr
- expected(__unexpect_inv, _Fn&& __fn)
- : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false)
- { }
- union {
- _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>>
- >;
- template<typename _Up>
- static constexpr bool __same_val
- = is_same_v<typename _Up::value_type, _Tp>;
- template<typename _Up>
- static constexpr bool __same_err
- = is_same_v<typename _Up::error_type, _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
- : _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)
- { }
- 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);
- }
- template<typename _Gr = _Er>
- constexpr _Er
- error_or(_Gr&& __e) const&
- {
- static_assert( is_copy_constructible_v<_Er> );
- static_assert( is_convertible_v<_Gr, _Er> );
- if (_M_has_value)
- return std::forward<_Gr>(__e);
- return _M_unex;
- }
- template<typename _Gr = _Er>
- constexpr _Er
- error_or(_Gr&& __e) &&
- {
- static_assert( is_move_constructible_v<_Er> );
- static_assert( is_convertible_v<_Gr, _Er> );
- if (_M_has_value)
- return std::forward<_Gr>(__e);
- return std::move(_M_unex);
- }
- // monadic operations
- template<typename _Fn> requires is_constructible_v<_Er, _Er&>
- constexpr auto
- and_then(_Fn&& __f) &
- {
- using _Up = __expected::__result0<_Fn>;
- static_assert(__expected::__is_expected<_Up>);
- static_assert(is_same_v<typename _Up::error_type, _Er>);
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f));
- else
- return _Up(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er&>
- constexpr auto
- and_then(_Fn&& __f) const &
- {
- using _Up = __expected::__result0<_Fn>;
- static_assert(__expected::__is_expected<_Up>);
- static_assert(is_same_v<typename _Up::error_type, _Er>);
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f));
- else
- return _Up(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, _Er>
- constexpr auto
- and_then(_Fn&& __f) &&
- {
- using _Up = __expected::__result0<_Fn>;
- static_assert(__expected::__is_expected<_Up>);
- static_assert(is_same_v<typename _Up::error_type, _Er>);
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f));
- else
- return _Up(unexpect, std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er>
- constexpr auto
- and_then(_Fn&& __f) const &&
- {
- using _Up = __expected::__result0<_Fn>;
- static_assert(__expected::__is_expected<_Up>);
- static_assert(is_same_v<typename _Up::error_type, _Er>);
- if (has_value())
- return std::__invoke(std::forward<_Fn>(__f));
- else
- return _Up(unexpect, std::move(_M_unex));
- }
- template<typename _Fn>
- constexpr auto
- or_else(_Fn&& __f) &
- {
- using _Gr = __expected::__result<_Fn, _Er&>;
- static_assert(__expected::__is_expected<_Gr>);
- static_assert(is_same_v<typename _Gr::value_type, _Tp>);
- if (has_value())
- return _Gr();
- else
- return std::__invoke(std::forward<_Fn>(__f), _M_unex);
- }
- template<typename _Fn>
- constexpr auto
- or_else(_Fn&& __f) const &
- {
- using _Gr = __expected::__result<_Fn, const _Er&>;
- static_assert(__expected::__is_expected<_Gr>);
- static_assert(is_same_v<typename _Gr::value_type, _Tp>);
- if (has_value())
- return _Gr();
- else
- return std::__invoke(std::forward<_Fn>(__f), _M_unex);
- }
- template<typename _Fn>
- constexpr auto
- or_else(_Fn&& __f) &&
- {
- using _Gr = __expected::__result<_Fn, _Er&&>;
- static_assert(__expected::__is_expected<_Gr>);
- static_assert(is_same_v<typename _Gr::value_type, _Tp>);
- if (has_value())
- return _Gr();
- else
- return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex));
- }
- template<typename _Fn>
- constexpr auto
- or_else(_Fn&& __f) const &&
- {
- using _Gr = __expected::__result<_Fn, const _Er&&>;
- static_assert(__expected::__is_expected<_Gr>);
- static_assert(is_same_v<typename _Gr::value_type, _Tp>);
- if (has_value())
- return _Gr();
- else
- return std::__invoke(std::forward<_Fn>(__f), std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Er, _Er&>
- constexpr auto
- transform(_Fn&& __f) &
- {
- using _Up = __expected::__result0_xform<_Fn>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
- else
- return _Res(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er&>
- constexpr auto
- transform(_Fn&& __f) const &
- {
- using _Up = __expected::__result0_xform<_Fn>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
- else
- return _Res(unexpect, _M_unex);
- }
- template<typename _Fn> requires is_constructible_v<_Er, _Er>
- constexpr auto
- transform(_Fn&& __f) &&
- {
- using _Up = __expected::__result0_xform<_Fn>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
- else
- return _Res(unexpect, std::move(_M_unex));
- }
- template<typename _Fn> requires is_constructible_v<_Er, const _Er>
- constexpr auto
- transform(_Fn&& __f) const &&
- {
- using _Up = __expected::__result0_xform<_Fn>;
- using _Res = expected<_Up, _Er>;
- if (has_value())
- return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
- else
- return _Res(unexpect, std::move(_M_unex));
- }
- template<typename _Fn>
- constexpr auto
- transform_error(_Fn&& __f) &
- {
- using _Gr = __expected::__result_xform<_Fn, _Er&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res();
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- _M_unex);
- });
- }
- template<typename _Fn>
- constexpr auto
- transform_error(_Fn&& __f) const &
- {
- using _Gr = __expected::__result_xform<_Fn, const _Er&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res();
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- _M_unex);
- });
- }
- template<typename _Fn>
- constexpr auto
- transform_error(_Fn&& __f) &&
- {
- using _Gr = __expected::__result_xform<_Fn, _Er&&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res();
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- std::move(_M_unex));
- });
- }
- template<typename _Fn>
- constexpr auto
- transform_error(_Fn&& __f) const &&
- {
- using _Gr = __expected::__result_xform<_Fn, const _Er&&>;
- using _Res = expected<_Tp, _Gr>;
- if (has_value())
- return _Res();
- else
- return _Res(__unexpect_inv{}, [&]() {
- return std::__invoke(std::forward<_Fn>(__f),
- 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)
- // FIXME: 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)
- // FIXME: 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);
- }
- using __in_place_inv = __expected::__in_place_inv;
- using __unexpect_inv = __expected::__unexpect_inv;
- template<typename _Fn>
- explicit constexpr
- expected(__in_place_inv, _Fn&& __fn)
- : _M_void(), _M_has_value(true)
- { std::forward<_Fn>(__fn)(); }
- template<typename _Fn>
- explicit constexpr
- expected(__unexpect_inv, _Fn&& __fn)
- : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false)
- { }
- union {
- struct { } _M_void;
- _Er _M_unex;
- };
- bool _M_has_value;
- };
- /// @}
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
- #endif // C++23
- #endif // _GLIBCXX_EXPECTED
|