1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326 |
- ///
- // expected - An implementation of std::expected with extensions
- // Written in 2017 by Simon Brand (simonrbrand@gmail.com, @TartanLlama)
- //
- // Documentation available at http://tl.tartanllama.xyz/
- //
- // To the extent possible under law, the author(s) have dedicated all
- // copyright and related and neighboring rights to this software to the
- // public domain worldwide. This software is distributed without any warranty.
- //
- // You should have received a copy of the CC0 Public Domain Dedication
- // along with this software. If not, see
- // <http://creativecommons.org/publicdomain/zero/1.0/>.
- ///
-
- #ifndef TL_EXPECTED_HPP
- #define TL_EXPECTED_HPP
-
- #define TL_EXPECTED_VERSION_MAJOR 1
- #define TL_EXPECTED_VERSION_MINOR 0
- #define TL_EXPECTED_VERSION_PATCH 1
-
- #include <exception>
- #include <functional>
- #include <type_traits>
- #include <utility>
-
- #if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
- #define TL_EXPECTED_EXCEPTIONS_ENABLED
- #endif
-
- #if (defined(_MSC_VER) && _MSC_VER == 1900)
- #define TL_EXPECTED_MSVC2015
- #define TL_EXPECTED_MSVC2015_CONSTEXPR
- #else
- #define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr
- #endif
-
- #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
- !defined(__clang__))
- #define TL_EXPECTED_GCC49
- #endif
-
- #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \
- !defined(__clang__))
- #define TL_EXPECTED_GCC54
- #endif
-
- #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \
- !defined(__clang__))
- #define TL_EXPECTED_GCC55
- #endif
-
- #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
- !defined(__clang__))
- // GCC < 5 doesn't support overloading on const&& for member functions
-
- #define TL_EXPECTED_NO_CONSTRR
- // GCC < 5 doesn't support some standard C++11 type traits
- #define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
- std::has_trivial_copy_constructor<T>
- #define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
- std::has_trivial_copy_assign<T>
-
- // This one will be different for GCC 5.7 if it's ever supported
- #define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
- std::is_trivially_destructible<T>
-
- // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
- // for non-copyable types
- #elif (defined(__GNUC__) && __GNUC__ < 8 && \
- !defined(__clang__))
- #ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
- #define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
- namespace tl {
- namespace detail {
- template<class T>
- struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T>{};
- #ifdef _GLIBCXX_VECTOR
- template<class T, class A>
- struct is_trivially_copy_constructible<std::vector<T,A>>
- : std::false_type{};
- #endif
- }
- }
- #endif
-
- #define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
- tl::detail::is_trivially_copy_constructible<T>
- #define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
- std::is_trivially_copy_assignable<T>
- #define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
- #else
- #define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
- std::is_trivially_copy_constructible<T>
- #define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
- std::is_trivially_copy_assignable<T>
- #define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
- std::is_trivially_destructible<T>
- #endif
-
- #if __cplusplus > 201103L
- #define TL_EXPECTED_CXX14
- #endif
-
- #ifdef TL_EXPECTED_GCC49
- #define TL_EXPECTED_GCC49_CONSTEXPR
- #else
- #define TL_EXPECTED_GCC49_CONSTEXPR constexpr
- #endif
-
- #if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \
- defined(TL_EXPECTED_GCC49))
- #define TL_EXPECTED_11_CONSTEXPR
- #else
- #define TL_EXPECTED_11_CONSTEXPR constexpr
- #endif
-
- namespace tl {
- template <class T, class E> class expected;
-
- #ifndef TL_MONOSTATE_INPLACE_MUTEX
- #define TL_MONOSTATE_INPLACE_MUTEX
- class monostate {};
-
- struct in_place_t {
- explicit in_place_t() = default;
- };
- static constexpr in_place_t in_place{};
- #endif
-
- template <class E> class unexpected {
- public:
- static_assert(!std::is_same<E, void>::value, "E must not be void");
-
- unexpected() = delete;
- constexpr explicit unexpected(const E &e) : m_val(e) {}
-
- constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {}
-
- constexpr const E &value() const & { return m_val; }
- TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; }
- TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); }
- constexpr const E &&value() const && { return std::move(m_val); }
-
- private:
- E m_val;
- };
-
- template <class E>
- constexpr bool operator==(const unexpected<E> &lhs, const unexpected<E> &rhs) {
- return lhs.value() == rhs.value();
- }
- template <class E>
- constexpr bool operator!=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
- return lhs.value() != rhs.value();
- }
- template <class E>
- constexpr bool operator<(const unexpected<E> &lhs, const unexpected<E> &rhs) {
- return lhs.value() < rhs.value();
- }
- template <class E>
- constexpr bool operator<=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
- return lhs.value() <= rhs.value();
- }
- template <class E>
- constexpr bool operator>(const unexpected<E> &lhs, const unexpected<E> &rhs) {
- return lhs.value() > rhs.value();
- }
- template <class E>
- constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
- return lhs.value() >= rhs.value();
- }
-
- template <class E>
- unexpected<typename std::decay<E>::type> make_unexpected(E &&e) {
- return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
- }
-
- struct unexpect_t {
- unexpect_t() = default;
- };
- static constexpr unexpect_t unexpect{};
-
- namespace detail {
- template<typename E>
- [[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) {
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- throw std::forward<E>(e);
- #else
- #ifdef _MSC_VER
- __assume(0);
- #else
- __builtin_unreachable();
- #endif
- #endif
- }
-
- #ifndef TL_TRAITS_MUTEX
- #define TL_TRAITS_MUTEX
- // C++14-style aliases for brevity
- template <class T> using remove_const_t = typename std::remove_const<T>::type;
- template <class T>
- using remove_reference_t = typename std::remove_reference<T>::type;
- template <class T> using decay_t = typename std::decay<T>::type;
- template <bool E, class T = void>
- using enable_if_t = typename std::enable_if<E, T>::type;
- template <bool B, class T, class F>
- using conditional_t = typename std::conditional<B, T, F>::type;
-
- // std::conjunction from C++17
- template <class...> struct conjunction : std::true_type {};
- template <class B> struct conjunction<B> : B {};
- template <class B, class... Bs>
- struct conjunction<B, Bs...>
- : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
-
- #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
- #define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
- #endif
-
- // In C++11 mode, there's an issue in libc++'s std::mem_fn
- // which results in a hard-error when using it in a noexcept expression
- // in some cases. This is a check to workaround the common failing case.
- #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
- template <class T> struct is_pointer_to_non_const_member_func : std::false_type {};
- template <class T, class Ret, class... Args>
- struct is_pointer_to_non_const_member_func<Ret(T::*) (Args...)> : std::true_type {};
- template <class T, class Ret, class... Args>
- struct is_pointer_to_non_const_member_func<Ret(T::*) (Args...)&> : std::true_type {};
- template <class T, class Ret, class... Args>
- struct is_pointer_to_non_const_member_func<Ret(T::*) (Args...) &&> : std::true_type {};
- template <class T, class Ret, class... Args>
- struct is_pointer_to_non_const_member_func<Ret(T::*) (Args...) volatile> : std::true_type {};
- template <class T, class Ret, class... Args>
- struct is_pointer_to_non_const_member_func<Ret(T::*) (Args...) volatile &> : std::true_type {};
- template <class T, class Ret, class... Args>
- struct is_pointer_to_non_const_member_func<Ret(T::*) (Args...) volatile &&> : std::true_type {};
-
- template <class T> struct is_const_or_const_ref : std::false_type {};
- template <class T> struct is_const_or_const_ref<T const&> : std::true_type {};
- template <class T> struct is_const_or_const_ref<T const> : std::true_type {};
- #endif
-
- // std::invoke from C++17
- // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
- template <typename Fn, typename... Args,
- #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
- typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value
- && is_const_or_const_ref<Args...>::value)>,
- #endif
- typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
- int = 0>
- constexpr auto invoke(Fn && f, Args && ... args) noexcept(
- noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
- -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
- return std::mem_fn(f)(std::forward<Args>(args)...);
- }
-
- template <typename Fn, typename... Args,
- typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
- constexpr auto invoke(Fn && f, Args && ... args) noexcept(
- noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
- -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
- return std::forward<Fn>(f)(std::forward<Args>(args)...);
- }
-
- // std::invoke_result from C++17
- template <class F, class, class... Us> struct invoke_result_impl;
-
- template <class F, class... Us>
- struct invoke_result_impl<
- F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),
- Us...> {
- using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
- };
-
- template <class F, class... Us>
- using invoke_result = invoke_result_impl<F, void, Us...>;
-
- template <class F, class... Us>
- using invoke_result_t = typename invoke_result<F, Us...>::type;
-
- #if defined(_MSC_VER) && _MSC_VER <= 1900
- // TODO make a version which works with MSVC 2015
- template <class T, class U = T> struct is_swappable : std::true_type {};
-
- template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
- #else
- // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
- namespace swap_adl_tests {
- // if swap ADL finds this then it would call std::swap otherwise (same
- // signature)
- struct tag {};
-
- template <class T> tag swap(T&, T&);
- template <class T, std::size_t N> tag swap(T(&a)[N], T(&b)[N]);
-
- // helper functions to test if an unqualified swap is possible, and if it
- // becomes std::swap
- template <class, class> std::false_type can_swap(...) noexcept(false);
- template <class T, class U,
- class = decltype(swap(std::declval<T&>(), std::declval<U&>()))>
- std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T&>(),
- std::declval<U&>())));
-
- template <class, class> std::false_type uses_std(...);
- template <class T, class U>
- std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag>
- uses_std(int);
-
- template <class T>
- struct is_std_swap_noexcept
- : std::integral_constant<bool,
- std::is_nothrow_move_constructible<T>::value&&
- std::is_nothrow_move_assignable<T>::value> {};
-
- template <class T, std::size_t N>
- struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
-
- template <class T, class U>
- struct is_adl_swap_noexcept
- : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
- } // namespace swap_adl_tests
-
- template <class T, class U = T>
- struct is_swappable
- : std::integral_constant<
- bool,
- decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
- (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
- (std::is_move_assignable<T>::value &&
- std::is_move_constructible<T>::value))> {};
-
- template <class T, std::size_t N>
- struct is_swappable<T[N], T[N]>
- : std::integral_constant<
- bool,
- decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
- (!decltype(
- detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
- is_swappable<T, T>::value)> {};
-
- template <class T, class U = T>
- struct is_nothrow_swappable
- : std::integral_constant<
- bool,
- is_swappable<T, U>::value &&
- ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
- && detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
- (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
- detail::swap_adl_tests::is_adl_swap_noexcept<T,
- U>::value))> {
- };
- #endif
- #endif
-
- // Trait for checking if a type is a tl::expected
- template <class T> struct is_expected_impl : std::false_type {};
- template <class T, class E>
- struct is_expected_impl<expected<T, E>> : std::true_type {};
- template <class T> using is_expected = is_expected_impl<decay_t<T>>;
-
- template <class T, class E, class U>
- using expected_enable_forward_value = detail::enable_if_t<
- std::is_constructible<T, U &&>::value &&
- !std::is_same<detail::decay_t<U>, in_place_t>::value &&
- !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
- !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
-
- template <class T, class E, class U, class G, class UR, class GR>
- using expected_enable_from_other = detail::enable_if_t<
- std::is_constructible<T, UR>::value &&
- std::is_constructible<E, GR>::value &&
- !std::is_constructible<T, expected<U, G> &>::value &&
- !std::is_constructible<T, expected<U, G> &&>::value &&
- !std::is_constructible<T, const expected<U, G> &>::value &&
- !std::is_constructible<T, const expected<U, G> &&>::value &&
- !std::is_convertible<expected<U, G> &, T>::value &&
- !std::is_convertible<expected<U, G> &&, T>::value &&
- !std::is_convertible<const expected<U, G> &, T>::value &&
- !std::is_convertible<const expected<U, G> &&, T>::value>;
-
- template <class T, class U>
- using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
-
- template <class T>
- using is_copy_constructible_or_void =
- is_void_or<T, std::is_copy_constructible<T>>;
-
- template <class T>
- using is_move_constructible_or_void =
- is_void_or<T, std::is_move_constructible<T>>;
-
- template <class T>
- using is_copy_assignable_or_void =
- is_void_or<T, std::is_copy_assignable<T>>;
-
-
- template <class T>
- using is_move_assignable_or_void =
- is_void_or<T, std::is_move_assignable<T>>;
-
-
- } // namespace detail
-
- namespace detail {
- struct no_init_t {};
- static constexpr no_init_t no_init{};
-
- // Implements the storage of the values, and ensures that the destructor is
- // trivial if it can be.
- //
- // This specialization is for where neither `T` or `E` is trivially
- // destructible, so the destructors must be called on destruction of the
- // `expected`
- template <class T, class E, bool = std::is_trivially_destructible<T>::value,
- bool = std::is_trivially_destructible<E>::value>
- struct expected_storage_base {
- constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
- constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
- nullptr>
- constexpr expected_storage_base(in_place_t, Args &&... args)
- : m_val(std::forward<Args>(args)...), m_has_val(true) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
- Args &&... args)
- : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
- template <class... Args,
- detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
- nullptr>
- constexpr explicit expected_storage_base(unexpect_t, Args &&... args)
- : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr explicit expected_storage_base(unexpect_t,
- std::initializer_list<U> il,
- Args &&... args)
- : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
-
- ~expected_storage_base() {
- if (m_has_val) {
- m_val.~T();
- } else {
- m_unexpect.~unexpected<E>();
- }
- }
- union {
- T m_val;
- unexpected<E> m_unexpect;
- char m_no_init;
- };
- bool m_has_val;
- };
-
- // This specialization is for when both `T` and `E` are trivially-destructible,
- // so the destructor of the `expected` can be trivial.
- template <class T, class E> struct expected_storage_base<T, E, true, true> {
- constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
- constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
- nullptr>
- constexpr expected_storage_base(in_place_t, Args &&... args)
- : m_val(std::forward<Args>(args)...), m_has_val(true) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
- Args &&... args)
- : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
- template <class... Args,
- detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
- nullptr>
- constexpr explicit expected_storage_base(unexpect_t, Args &&... args)
- : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr explicit expected_storage_base(unexpect_t,
- std::initializer_list<U> il,
- Args &&... args)
- : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
-
- ~expected_storage_base() = default;
- union {
- T m_val;
- unexpected<E> m_unexpect;
- char m_no_init;
- };
- bool m_has_val;
- };
-
- // T is trivial, E is not.
- template <class T, class E> struct expected_storage_base<T, E, true, false> {
- constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
- TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t)
- : m_no_init(), m_has_val(false) {}
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
- nullptr>
- constexpr expected_storage_base(in_place_t, Args &&... args)
- : m_val(std::forward<Args>(args)...), m_has_val(true) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
- Args &&... args)
- : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
- template <class... Args,
- detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
- nullptr>
- constexpr explicit expected_storage_base(unexpect_t, Args &&... args)
- : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr explicit expected_storage_base(unexpect_t,
- std::initializer_list<U> il,
- Args &&... args)
- : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
-
- ~expected_storage_base() {
- if (!m_has_val) {
- m_unexpect.~unexpected<E>();
- }
- }
-
- union {
- T m_val;
- unexpected<E> m_unexpect;
- char m_no_init;
- };
- bool m_has_val;
- };
-
- // E is trivial, T is not.
- template <class T, class E> struct expected_storage_base<T, E, false, true> {
- constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
- constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
- nullptr>
- constexpr expected_storage_base(in_place_t, Args &&... args)
- : m_val(std::forward<Args>(args)...), m_has_val(true) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
- Args &&... args)
- : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
- template <class... Args,
- detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
- nullptr>
- constexpr explicit expected_storage_base(unexpect_t, Args &&... args)
- : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr explicit expected_storage_base(unexpect_t,
- std::initializer_list<U> il,
- Args &&... args)
- : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
-
- ~expected_storage_base() {
- if (m_has_val) {
- m_val.~T();
- }
- }
- union {
- T m_val;
- unexpected<E> m_unexpect;
- char m_no_init;
- };
- bool m_has_val;
- };
-
- // `T` is `void`, `E` is trivially-destructible
- template <class E> struct expected_storage_base<void, E, false, true> {
- TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base() : m_has_val(true) {}
- constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {}
-
- constexpr expected_storage_base(in_place_t) : m_has_val(true) {}
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
- nullptr>
- constexpr explicit expected_storage_base(unexpect_t, Args &&... args)
- : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr explicit expected_storage_base(unexpect_t,
- std::initializer_list<U> il,
- Args &&... args)
- : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
-
- ~expected_storage_base() = default;
- struct dummy {};
- union {
- unexpected<E> m_unexpect;
- dummy m_val;
- };
- bool m_has_val;
- };
-
- // `T` is `void`, `E` is not trivially-destructible
- template <class E> struct expected_storage_base<void, E, false, false> {
- constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
- constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {}
-
- constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {}
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
- nullptr>
- constexpr explicit expected_storage_base(unexpect_t, Args &&... args)
- : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr explicit expected_storage_base(unexpect_t,
- std::initializer_list<U> il,
- Args &&... args)
- : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
-
- ~expected_storage_base() {
- if (!m_has_val) {
- m_unexpect.~unexpected<E>();
- }
- }
-
- union {
- unexpected<E> m_unexpect;
- char m_dummy;
- };
- bool m_has_val;
- };
-
- // This base class provides some handy member functions which can be used in
- // further derived classes
- template <class T, class E>
- struct expected_operations_base : expected_storage_base<T, E> {
- using expected_storage_base<T, E>::expected_storage_base;
-
- template <class... Args> void construct(Args &&... args) noexcept {
- new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
- this->m_has_val = true;
- }
-
- template <class Rhs> void construct_with(Rhs &&rhs) noexcept {
- new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
- this->m_has_val = true;
- }
-
- template <class... Args> void construct_error(Args &&... args) noexcept {
- new (std::addressof(this->m_unexpect))
- unexpected<E>(std::forward<Args>(args)...);
- this->m_has_val = false;
- }
-
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
-
- // These assign overloads ensure that the most efficient assignment
- // implementation is used while maintaining the strong exception guarantee.
- // The problematic case is where rhs has a value, but *this does not.
- //
- // This overload handles the case where we can just copy-construct `T`
- // directly into place without throwing.
- template <class U = T,
- detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value>
- * = nullptr>
- void assign(const expected_operations_base &rhs) noexcept {
- if (!this->m_has_val && rhs.m_has_val) {
- geterr().~unexpected<E>();
- construct(rhs.get());
- } else {
- assign_common(rhs);
- }
- }
-
- // This overload handles the case where we can attempt to create a copy of
- // `T`, then no-throw move it into place if the copy was successful.
- template <class U = T,
- detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
- std::is_nothrow_move_constructible<U>::value>
- * = nullptr>
- void assign(const expected_operations_base &rhs) noexcept {
- if (!this->m_has_val && rhs.m_has_val) {
- T tmp = rhs.get();
- geterr().~unexpected<E>();
- construct(std::move(tmp));
- } else {
- assign_common(rhs);
- }
- }
-
- // This overload is the worst-case, where we have to move-construct the
- // unexpected value into temporary storage, then try to copy the T into place.
- // If the construction succeeds, then everything is fine, but if it throws,
- // then we move the old unexpected value back into place before rethrowing the
- // exception.
- template <class U = T,
- detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
- !std::is_nothrow_move_constructible<U>::value>
- * = nullptr>
- void assign(const expected_operations_base &rhs) {
- if (!this->m_has_val && rhs.m_has_val) {
- auto tmp = std::move(geterr());
- geterr().~unexpected<E>();
-
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- try {
- construct(rhs.get());
- } catch (...) {
- geterr() = std::move(tmp);
- throw;
- }
- #else
- construct(rhs.get());
- #endif
- } else {
- assign_common(rhs);
- }
- }
-
- // These overloads do the same as above, but for rvalues
- template <class U = T,
- detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>
- * = nullptr>
- void assign(expected_operations_base &&rhs) noexcept {
- if (!this->m_has_val && rhs.m_has_val) {
- geterr().~unexpected<E>();
- construct(std::move(rhs).get());
- } else {
- assign_common(std::move(rhs));
- }
- }
-
- template <class U = T,
- detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
- * = nullptr>
- void assign(expected_operations_base &&rhs) {
- if (!this->m_has_val && rhs.m_has_val) {
- auto tmp = std::move(geterr());
- geterr().~unexpected<E>();
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- try {
- construct(std::move(rhs).get());
- } catch (...) {
- geterr() = std::move(tmp);
- throw;
- }
- #else
- construct(std::move(rhs).get());
- #endif
- } else {
- assign_common(std::move(rhs));
- }
- }
-
- #else
-
- // If exceptions are disabled then we can just copy-construct
- void assign(const expected_operations_base &rhs) noexcept {
- if (!this->m_has_val && rhs.m_has_val) {
- geterr().~unexpected<E>();
- construct(rhs.get());
- } else {
- assign_common(rhs);
- }
- }
-
- void assign(expected_operations_base &&rhs) noexcept {
- if (!this->m_has_val && rhs.m_has_val) {
- geterr().~unexpected<E>();
- construct(std::move(rhs).get());
- } else {
- assign_common(rhs);
- }
- }
-
- #endif
-
- // The common part of move/copy assigning
- template <class Rhs> void assign_common(Rhs &&rhs) {
- if (this->m_has_val) {
- if (rhs.m_has_val) {
- get() = std::forward<Rhs>(rhs).get();
- } else {
- destroy_val();
- construct_error(std::forward<Rhs>(rhs).geterr());
- }
- } else {
- if (!rhs.m_has_val) {
- geterr() = std::forward<Rhs>(rhs).geterr();
- }
- }
- }
-
- bool has_value() const { return this->m_has_val; }
-
- TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; }
- constexpr const T &get() const & { return this->m_val; }
- TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); }
- #ifndef TL_EXPECTED_NO_CONSTRR
- constexpr const T &&get() const && { return std::move(this->m_val); }
- #endif
-
- TL_EXPECTED_11_CONSTEXPR unexpected<E> &geterr() & {
- return this->m_unexpect;
- }
- constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
- TL_EXPECTED_11_CONSTEXPR unexpected<E> &&geterr() && {
- return std::move(this->m_unexpect);
- }
- #ifndef TL_EXPECTED_NO_CONSTRR
- constexpr const unexpected<E> &&geterr() const && {
- return std::move(this->m_unexpect);
- }
- #endif
-
- TL_EXPECTED_11_CONSTEXPR void destroy_val() {
- get().~T();
- }
- };
-
- // This base class provides some handy member functions which can be used in
- // further derived classes
- template <class E>
- struct expected_operations_base<void, E> : expected_storage_base<void, E> {
- using expected_storage_base<void, E>::expected_storage_base;
-
- template <class... Args> void construct() noexcept { this->m_has_val = true; }
-
- // This function doesn't use its argument, but needs it so that code in
- // levels above this can work independently of whether T is void
- template <class Rhs> void construct_with(Rhs &&) noexcept {
- this->m_has_val = true;
- }
-
- template <class... Args> void construct_error(Args &&... args) noexcept {
- new (std::addressof(this->m_unexpect))
- unexpected<E>(std::forward<Args>(args)...);
- this->m_has_val = false;
- }
-
- template <class Rhs> void assign(Rhs &&rhs) noexcept {
- if (!this->m_has_val) {
- if (rhs.m_has_val) {
- geterr().~unexpected<E>();
- construct();
- } else {
- geterr() = std::forward<Rhs>(rhs).geterr();
- }
- } else {
- if (!rhs.m_has_val) {
- construct_error(std::forward<Rhs>(rhs).geterr());
- }
- }
- }
-
- bool has_value() const { return this->m_has_val; }
-
- TL_EXPECTED_11_CONSTEXPR unexpected<E> &geterr() & {
- return this->m_unexpect;
- }
- constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
- TL_EXPECTED_11_CONSTEXPR unexpected<E> &&geterr() && {
- return std::move(this->m_unexpect);
- }
- #ifndef TL_EXPECTED_NO_CONSTRR
- constexpr const unexpected<E> &&geterr() const && {
- return std::move(this->m_unexpect);
- }
- #endif
-
- TL_EXPECTED_11_CONSTEXPR void destroy_val() {
- //no-op
- }
- };
-
- // This class manages conditionally having a trivial copy constructor
- // This specialization is for when T and E are trivially copy constructible
- template <class T, class E,
- bool = is_void_or<T, TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::
- value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
- struct expected_copy_base : expected_operations_base<T, E> {
- using expected_operations_base<T, E>::expected_operations_base;
- };
-
- // This specialization is for when T or E are not trivially copy constructible
- template <class T, class E>
- struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
- using expected_operations_base<T, E>::expected_operations_base;
-
- expected_copy_base() = default;
- expected_copy_base(const expected_copy_base &rhs)
- : expected_operations_base<T, E>(no_init) {
- if (rhs.has_value()) {
- this->construct_with(rhs);
- } else {
- this->construct_error(rhs.geterr());
- }
- }
-
- expected_copy_base(expected_copy_base &&rhs) = default;
- expected_copy_base &operator=(const expected_copy_base &rhs) = default;
- expected_copy_base &operator=(expected_copy_base &&rhs) = default;
- };
-
- // This class manages conditionally having a trivial move constructor
- // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
- // doesn't implement an analogue to std::is_trivially_move_constructible. We
- // have to make do with a non-trivial move constructor even if T is trivially
- // move constructible
- #ifndef TL_EXPECTED_GCC49
- template <class T, class E,
- bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value
- &&std::is_trivially_move_constructible<E>::value>
- struct expected_move_base : expected_copy_base<T, E> {
- using expected_copy_base<T, E>::expected_copy_base;
- };
- #else
- template <class T, class E, bool = false> struct expected_move_base;
- #endif
- template <class T, class E>
- struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
- using expected_copy_base<T, E>::expected_copy_base;
-
- expected_move_base() = default;
- expected_move_base(const expected_move_base &rhs) = default;
-
- expected_move_base(expected_move_base &&rhs) noexcept(
- std::is_nothrow_move_constructible<T>::value)
- : expected_copy_base<T, E>(no_init) {
- if (rhs.has_value()) {
- this->construct_with(std::move(rhs));
- } else {
- this->construct_error(std::move(rhs.geterr()));
- }
- }
- expected_move_base &operator=(const expected_move_base &rhs) = default;
- expected_move_base &operator=(expected_move_base &&rhs) = default;
- };
-
- // This class manages conditionally having a trivial copy assignment operator
- template <class T, class E,
- bool = is_void_or<
- T, conjunction<TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
- TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
- TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value
- &&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value
- &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value
- &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
- struct expected_copy_assign_base : expected_move_base<T, E> {
- using expected_move_base<T, E>::expected_move_base;
- };
-
- template <class T, class E>
- struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
- using expected_move_base<T, E>::expected_move_base;
-
- expected_copy_assign_base() = default;
- expected_copy_assign_base(const expected_copy_assign_base &rhs) = default;
-
- expected_copy_assign_base(expected_copy_assign_base &&rhs) = default;
- expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) {
- this->assign(rhs);
- return *this;
- }
- expected_copy_assign_base &
- operator=(expected_copy_assign_base &&rhs) = default;
- };
-
- // This class manages conditionally having a trivial move assignment operator
- // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
- // doesn't implement an analogue to std::is_trivially_move_assignable. We have
- // to make do with a non-trivial move assignment operator even if T is trivially
- // move assignable
- #ifndef TL_EXPECTED_GCC49
- template <class T, class E,
- bool =
- is_void_or<T, conjunction<std::is_trivially_destructible<T>,
- std::is_trivially_move_constructible<T>,
- std::is_trivially_move_assignable<T>>>::
- value &&std::is_trivially_destructible<E>::value
- &&std::is_trivially_move_constructible<E>::value
- &&std::is_trivially_move_assignable<E>::value>
- struct expected_move_assign_base : expected_copy_assign_base<T, E> {
- using expected_copy_assign_base<T, E>::expected_copy_assign_base;
- };
- #else
- template <class T, class E, bool = false> struct expected_move_assign_base;
- #endif
-
- template <class T, class E>
- struct expected_move_assign_base<T, E, false>
- : expected_copy_assign_base<T, E> {
- using expected_copy_assign_base<T, E>::expected_copy_assign_base;
-
- expected_move_assign_base() = default;
- expected_move_assign_base(const expected_move_assign_base &rhs) = default;
-
- expected_move_assign_base(expected_move_assign_base &&rhs) = default;
-
- expected_move_assign_base &
- operator=(const expected_move_assign_base &rhs) = default;
-
- expected_move_assign_base &
- operator=(expected_move_assign_base &&rhs) noexcept(
- std::is_nothrow_move_constructible<T>::value
- &&std::is_nothrow_move_assignable<T>::value) {
- this->assign(std::move(rhs));
- return *this;
- }
- };
-
- // expected_delete_ctor_base will conditionally delete copy and move
- // constructors depending on whether T is copy/move constructible
- template <class T, class E,
- bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
- std::is_copy_constructible<E>::value),
- bool EnableMove = (is_move_constructible_or_void<T>::value &&
- std::is_move_constructible<E>::value)>
- struct expected_delete_ctor_base {
- expected_delete_ctor_base() = default;
- expected_delete_ctor_base(const expected_delete_ctor_base &) = default;
- expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
- expected_delete_ctor_base &
- operator=(const expected_delete_ctor_base &) = default;
- expected_delete_ctor_base &
- operator=(expected_delete_ctor_base &&) noexcept = default;
- };
-
- template <class T, class E>
- struct expected_delete_ctor_base<T, E, true, false> {
- expected_delete_ctor_base() = default;
- expected_delete_ctor_base(const expected_delete_ctor_base &) = default;
- expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
- expected_delete_ctor_base &
- operator=(const expected_delete_ctor_base &) = default;
- expected_delete_ctor_base &
- operator=(expected_delete_ctor_base &&) noexcept = default;
- };
-
- template <class T, class E>
- struct expected_delete_ctor_base<T, E, false, true> {
- expected_delete_ctor_base() = default;
- expected_delete_ctor_base(const expected_delete_ctor_base &) = delete;
- expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
- expected_delete_ctor_base &
- operator=(const expected_delete_ctor_base &) = default;
- expected_delete_ctor_base &
- operator=(expected_delete_ctor_base &&) noexcept = default;
- };
-
- template <class T, class E>
- struct expected_delete_ctor_base<T, E, false, false> {
- expected_delete_ctor_base() = default;
- expected_delete_ctor_base(const expected_delete_ctor_base &) = delete;
- expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
- expected_delete_ctor_base &
- operator=(const expected_delete_ctor_base &) = default;
- expected_delete_ctor_base &
- operator=(expected_delete_ctor_base &&) noexcept = default;
- };
-
- // expected_delete_assign_base will conditionally delete copy and move
- // constructors depending on whether T and E are copy/move constructible +
- // assignable
- template <class T, class E,
- bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
- std::is_copy_constructible<E>::value &&
- is_copy_assignable_or_void<T>::value &&
- std::is_copy_assignable<E>::value),
- bool EnableMove = (is_move_constructible_or_void<T>::value &&
- std::is_move_constructible<E>::value &&
- is_move_assignable_or_void<T>::value &&
- std::is_move_assignable<E>::value)>
- struct expected_delete_assign_base {
- expected_delete_assign_base() = default;
- expected_delete_assign_base(const expected_delete_assign_base &) = default;
- expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
- default;
- expected_delete_assign_base &
- operator=(const expected_delete_assign_base &) = default;
- expected_delete_assign_base &
- operator=(expected_delete_assign_base &&) noexcept = default;
- };
-
- template <class T, class E>
- struct expected_delete_assign_base<T, E, true, false> {
- expected_delete_assign_base() = default;
- expected_delete_assign_base(const expected_delete_assign_base &) = default;
- expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
- default;
- expected_delete_assign_base &
- operator=(const expected_delete_assign_base &) = default;
- expected_delete_assign_base &
- operator=(expected_delete_assign_base &&) noexcept = delete;
- };
-
- template <class T, class E>
- struct expected_delete_assign_base<T, E, false, true> {
- expected_delete_assign_base() = default;
- expected_delete_assign_base(const expected_delete_assign_base &) = default;
- expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
- default;
- expected_delete_assign_base &
- operator=(const expected_delete_assign_base &) = delete;
- expected_delete_assign_base &
- operator=(expected_delete_assign_base &&) noexcept = default;
- };
-
- template <class T, class E>
- struct expected_delete_assign_base<T, E, false, false> {
- expected_delete_assign_base() = default;
- expected_delete_assign_base(const expected_delete_assign_base &) = default;
- expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
- default;
- expected_delete_assign_base &
- operator=(const expected_delete_assign_base &) = delete;
- expected_delete_assign_base &
- operator=(expected_delete_assign_base &&) noexcept = delete;
- };
-
- // This is needed to be able to construct the expected_default_ctor_base which
- // follows, while still conditionally deleting the default constructor.
- struct default_constructor_tag {
- explicit constexpr default_constructor_tag() = default;
- };
-
- // expected_default_ctor_base will ensure that expected has a deleted default
- // consturctor if T is not default constructible.
- // This specialization is for when T is default constructible
- template <class T, class E,
- bool Enable =
- std::is_default_constructible<T>::value || std::is_void<T>::value>
- struct expected_default_ctor_base {
- constexpr expected_default_ctor_base() noexcept = default;
- constexpr expected_default_ctor_base(
- expected_default_ctor_base const &) noexcept = default;
- constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
- default;
- expected_default_ctor_base &
- operator=(expected_default_ctor_base const &) noexcept = default;
- expected_default_ctor_base &
- operator=(expected_default_ctor_base &&) noexcept = default;
-
- constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
- };
-
- // This specialization is for when T is not default constructible
- template <class T, class E> struct expected_default_ctor_base<T, E, false> {
- constexpr expected_default_ctor_base() noexcept = delete;
- constexpr expected_default_ctor_base(
- expected_default_ctor_base const &) noexcept = default;
- constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
- default;
- expected_default_ctor_base &
- operator=(expected_default_ctor_base const &) noexcept = default;
- expected_default_ctor_base &
- operator=(expected_default_ctor_base &&) noexcept = default;
-
- constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
- };
- } // namespace detail
-
- template <class E> class bad_expected_access : public std::exception {
- public:
- explicit bad_expected_access(E e) : m_val(std::move(e)) {}
-
- virtual const char *what() const noexcept override {
- return "Bad expected access";
- }
-
- const E &error() const & { return m_val; }
- E &error() & { return m_val; }
- const E &&error() const && { return std::move(m_val); }
- E &&error() && { return std::move(m_val); }
-
- private:
- E m_val;
- };
-
- /// An `expected<T, E>` object is an object that contains the storage for
- /// another object and manages the lifetime of this contained object `T`.
- /// Alternatively it could contain the storage for another unexpected object
- /// `E`. The contained object may not be initialized after the expected object
- /// has been initialized, and may not be destroyed before the expected object
- /// has been destroyed. The initialization state of the contained object is
- /// tracked by the expected object.
- template <class T, class E>
- class expected : private detail::expected_move_assign_base<T, E>,
- private detail::expected_delete_ctor_base<T, E>,
- private detail::expected_delete_assign_base<T, E>,
- private detail::expected_default_ctor_base<T, E> {
- static_assert(!std::is_reference<T>::value, "T must not be a reference");
- static_assert(!std::is_same<T, std::remove_cv<in_place_t>>::value,
- "T must not be in_place_t");
- static_assert(!std::is_same<T, std::remove_cv<unexpect_t>>::value,
- "T must not be unexpect_t");
- static_assert(!std::is_same<T, std::remove_cv<unexpected<E>>>::value,
- "T must not be unexpected<E>");
- static_assert(!std::is_reference<E>::value, "E must not be a reference");
-
- T *valptr() { return std::addressof(this->m_val); }
- const T *valptr() const { return std::addressof(this->m_val); }
- unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }
- const unexpected<E> *errptr() const { return std::addressof(this->m_unexpect); }
-
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR U &val() {
- return this->m_val;
- }
- TL_EXPECTED_11_CONSTEXPR unexpected<E> &err() { return this->m_unexpect; }
-
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- constexpr const U &val() const {
- return this->m_val;
- }
- constexpr const unexpected<E> &err() const { return this->m_unexpect; }
-
- using impl_base = detail::expected_move_assign_base<T, E>;
- using ctor_base = detail::expected_default_ctor_base<T, E>;
-
- public:
- typedef T value_type;
- typedef E error_type;
- typedef unexpected<E> unexpected_type;
-
- #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
- !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
- template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {
- return and_then_impl(*this, std::forward<F>(f));
- }
- template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {
- return and_then_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F> constexpr auto and_then(F &&f) const & {
- return and_then_impl(*this, std::forward<F>(f));
- }
-
- #ifndef TL_EXPECTED_NO_CONSTRR
- template <class F> constexpr auto and_then(F &&f) const && {
- return and_then_impl(std::move(*this), std::forward<F>(f));
- }
- #endif
-
- #else
- template <class F>
- TL_EXPECTED_11_CONSTEXPR auto
- and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected&>(), std::forward<F>(f))) {
- return and_then_impl(*this, std::forward<F>(f));
- }
- template <class F>
- TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(
- and_then_impl(std::declval<expected&&>(), std::forward<F>(f))) {
- return and_then_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F>
- constexpr auto and_then(F &&f) const & -> decltype(
- and_then_impl(std::declval<expected const&>(), std::forward<F>(f))) {
- return and_then_impl(*this, std::forward<F>(f));
- }
-
- #ifndef TL_EXPECTED_NO_CONSTRR
- template <class F>
- constexpr auto and_then(F &&f) const && -> decltype(
- and_then_impl(std::declval<expected const&&>(), std::forward<F>(f))) {
- return and_then_impl(std::move(*this), std::forward<F>(f));
- }
- #endif
- #endif
-
- #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
- !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
- template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
- template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F> constexpr auto map(F &&f) const & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
- template <class F> constexpr auto map(F &&f) const && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- #else
- template <class F>
- TL_EXPECTED_11_CONSTEXPR decltype(
- expected_map_impl(std::declval<expected &>(), std::declval<F &&>()))
- map(F &&f) & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
- template <class F>
- TL_EXPECTED_11_CONSTEXPR decltype(
- expected_map_impl(std::declval<expected>(), std::declval<F &&>()))
- map(F &&f) && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F>
- constexpr decltype(expected_map_impl(std::declval<const expected &>(),
- std::declval<F &&>()))
- map(F &&f) const & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
-
- #ifndef TL_EXPECTED_NO_CONSTRR
- template <class F>
- constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
- std::declval<F &&>()))
- map(F &&f) const && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- #endif
- #endif
-
- #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
- !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
- template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
- template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F> constexpr auto transform(F &&f) const & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
- template <class F> constexpr auto transform(F &&f) const && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- #else
- template <class F>
- TL_EXPECTED_11_CONSTEXPR decltype(
- expected_map_impl(std::declval<expected &>(), std::declval<F &&>()))
- transform(F &&f) & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
- template <class F>
- TL_EXPECTED_11_CONSTEXPR decltype(
- expected_map_impl(std::declval<expected>(), std::declval<F &&>()))
- transform(F &&f) && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F>
- constexpr decltype(expected_map_impl(std::declval<const expected &>(),
- std::declval<F &&>()))
- transform(F &&f) const & {
- return expected_map_impl(*this, std::forward<F>(f));
- }
-
- #ifndef TL_EXPECTED_NO_CONSTRR
- template <class F>
- constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
- std::declval<F &&>()))
- transform(F &&f) const && {
- return expected_map_impl(std::move(*this), std::forward<F>(f));
- }
- #endif
- #endif
-
- #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
- !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
- template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & {
- return map_error_impl(*this, std::forward<F>(f));
- }
- template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && {
- return map_error_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F> constexpr auto map_error(F &&f) const & {
- return map_error_impl(*this, std::forward<F>(f));
- }
- template <class F> constexpr auto map_error(F &&f) const && {
- return map_error_impl(std::move(*this), std::forward<F>(f));
- }
- #else
- template <class F>
- TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),
- std::declval<F &&>()))
- map_error(F &&f) & {
- return map_error_impl(*this, std::forward<F>(f));
- }
- template <class F>
- TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),
- std::declval<F &&>()))
- map_error(F &&f) && {
- return map_error_impl(std::move(*this), std::forward<F>(f));
- }
- template <class F>
- constexpr decltype(map_error_impl(std::declval<const expected &>(),
- std::declval<F &&>()))
- map_error(F &&f) const & {
- return map_error_impl(*this, std::forward<F>(f));
- }
-
- #ifndef TL_EXPECTED_NO_CONSTRR
- template <class F>
- constexpr decltype(map_error_impl(std::declval<const expected &&>(),
- std::declval<F &&>()))
- map_error(F &&f) const && {
- return map_error_impl(std::move(*this), std::forward<F>(f));
- }
- #endif
- #endif
- template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & {
- return or_else_impl(*this, std::forward<F>(f));
- }
-
- template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && {
- return or_else_impl(std::move(*this), std::forward<F>(f));
- }
-
- template <class F> expected constexpr or_else(F &&f) const & {
- return or_else_impl(*this, std::forward<F>(f));
- }
-
- #ifndef TL_EXPECTED_NO_CONSTRR
- template <class F> expected constexpr or_else(F &&f) const && {
- return or_else_impl(std::move(*this), std::forward<F>(f));
- }
- #endif
- constexpr expected() = default;
- constexpr expected(const expected &rhs) = default;
- constexpr expected(expected &&rhs) = default;
- expected &operator=(const expected &rhs) = default;
- expected &operator=(expected &&rhs) = default;
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
- nullptr>
- constexpr expected(in_place_t, Args &&... args)
- : impl_base(in_place, std::forward<Args>(args)...),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr expected(in_place_t, std::initializer_list<U> il, Args &&... args)
- : impl_base(in_place, il, std::forward<Args>(args)...),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <class G = E,
- detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
- nullptr,
- detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
- nullptr>
- explicit constexpr expected(const unexpected<G> &e)
- : impl_base(unexpect, e.value()),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <
- class G = E,
- detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
- nullptr,
- detail::enable_if_t<std::is_convertible<const G &, E>::value> * = nullptr>
- constexpr expected(unexpected<G> const &e)
- : impl_base(unexpect, e.value()),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <
- class G = E,
- detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,
- detail::enable_if_t<!std::is_convertible<G &&, E>::value> * = nullptr>
- explicit constexpr expected(unexpected<G> &&e) noexcept(
- std::is_nothrow_constructible<E, G &&>::value)
- : impl_base(unexpect, std::move(e.value())),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <
- class G = E,
- detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,
- detail::enable_if_t<std::is_convertible<G &&, E>::value> * = nullptr>
- constexpr expected(unexpected<G> &&e) noexcept(
- std::is_nothrow_constructible<E, G &&>::value)
- : impl_base(unexpect, std::move(e.value())),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <class... Args,
- detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
- nullptr>
- constexpr explicit expected(unexpect_t, Args &&... args)
- : impl_base(unexpect, std::forward<Args>(args)...),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_constructible<
- E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- constexpr explicit expected(unexpect_t, std::initializer_list<U> il,
- Args &&... args)
- : impl_base(unexpect, il, std::forward<Args>(args)...),
- ctor_base(detail::default_constructor_tag{}) {}
-
- template <class U, class G,
- detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
- std::is_convertible<G const &, E>::value)> * =
- nullptr,
- detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
- * = nullptr>
- explicit TL_EXPECTED_11_CONSTEXPR expected(const expected<U, G> &rhs)
- : ctor_base(detail::default_constructor_tag{}) {
- if (rhs.has_value()) {
- this->construct(*rhs);
- } else {
- this->construct_error(rhs.error());
- }
- }
-
- template <class U, class G,
- detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
- std::is_convertible<G const &, E>::value)> * =
- nullptr,
- detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
- * = nullptr>
- TL_EXPECTED_11_CONSTEXPR expected(const expected<U, G> &rhs)
- : ctor_base(detail::default_constructor_tag{}) {
- if (rhs.has_value()) {
- this->construct(*rhs);
- } else {
- this->construct_error(rhs.error());
- }
- }
-
- template <
- class U, class G,
- detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&
- std::is_convertible<G &&, E>::value)> * = nullptr,
- detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>
- explicit TL_EXPECTED_11_CONSTEXPR expected(expected<U, G> &&rhs)
- : ctor_base(detail::default_constructor_tag{}) {
- if (rhs.has_value()) {
- this->construct(std::move(*rhs));
- } else {
- this->construct_error(std::move(rhs.error()));
- }
- }
-
- template <
- class U, class G,
- detail::enable_if_t<(std::is_convertible<U &&, T>::value &&
- std::is_convertible<G &&, E>::value)> * = nullptr,
- detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR expected(expected<U, G> &&rhs)
- : ctor_base(detail::default_constructor_tag{}) {
- if (rhs.has_value()) {
- this->construct(std::move(*rhs));
- } else {
- this->construct_error(std::move(rhs.error()));
- }
- }
-
- template <
- class U = T,
- detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
- detail::expected_enable_forward_value<T, E, U> * = nullptr>
- explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)
- : expected(in_place, std::forward<U>(v)) {}
-
- template <
- class U = T,
- detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
- detail::expected_enable_forward_value<T, E, U> * = nullptr>
- TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)
- : expected(in_place, std::forward<U>(v)) {}
-
- template <
- class U = T, class G = T,
- detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
- nullptr,
- detail::enable_if_t<!std::is_void<G>::value> * = nullptr,
- detail::enable_if_t<
- (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
- !detail::conjunction<std::is_scalar<T>,
- std::is_same<T, detail::decay_t<U>>>::value &&
- std::is_constructible<T, U>::value &&
- std::is_assignable<G &, U>::value &&
- std::is_nothrow_move_constructible<E>::value)> * = nullptr>
- expected &operator=(U &&v) {
- if (has_value()) {
- val() = std::forward<U>(v);
- } else {
- err().~unexpected<E>();
- ::new (valptr()) T(std::forward<U>(v));
- this->m_has_val = true;
- }
-
- return *this;
- }
-
- template <
- class U = T, class G = T,
- detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
- nullptr,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr,
- detail::enable_if_t<
- (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
- !detail::conjunction<std::is_scalar<T>,
- std::is_same<T, detail::decay_t<U>>>::value &&
- std::is_constructible<T, U>::value &&
- std::is_assignable<G &, U>::value &&
- std::is_nothrow_move_constructible<E>::value)> * = nullptr>
- expected &operator=(U &&v) {
- if (has_value()) {
- val() = std::forward<U>(v);
- } else {
- auto tmp = std::move(err());
- err().~unexpected<E>();
-
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- try {
- ::new (valptr()) T(std::forward<U>(v));
- this->m_has_val = true;
- } catch (...) {
- err() = std::move(tmp);
- throw;
- }
- #else
- ::new (valptr()) T(std::forward<U>(v));
- this->m_has_val = true;
- #endif
- }
-
- return *this;
- }
-
- template <class G = E,
- detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
- std::is_assignable<G &, G>::value> * = nullptr>
- expected &operator=(const unexpected<G> &rhs) {
- if (!has_value()) {
- err() = rhs;
- } else {
- this->destroy_val();
- ::new (errptr()) unexpected<E>(rhs);
- this->m_has_val = false;
- }
-
- return *this;
- }
-
- template <class G = E,
- detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
- std::is_move_assignable<G>::value> * = nullptr>
- expected &operator=(unexpected<G> &&rhs) noexcept {
- if (!has_value()) {
- err() = std::move(rhs);
- } else {
- this->destroy_val();
- ::new (errptr()) unexpected<E>(std::move(rhs));
- this->m_has_val = false;
- }
-
- return *this;
- }
-
- template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<
- T, Args &&...>::value> * = nullptr>
- void emplace(Args &&... args) {
- if (has_value()) {
- val() = T(std::forward<Args>(args)...);
- } else {
- err().~unexpected<E>();
- ::new (valptr()) T(std::forward<Args>(args)...);
- this->m_has_val = true;
- }
- }
-
- template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<
- T, Args &&...>::value> * = nullptr>
- void emplace(Args &&... args) {
- if (has_value()) {
- val() = T(std::forward<Args>(args)...);
- } else {
- auto tmp = std::move(err());
- err().~unexpected<E>();
-
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- try {
- ::new (valptr()) T(std::forward<Args>(args)...);
- this->m_has_val = true;
- } catch (...) {
- err() = std::move(tmp);
- throw;
- }
- #else
- ::new (valptr()) T(std::forward<Args>(args)...);
- this->m_has_val = true;
- #endif
- }
- }
-
- template <class U, class... Args,
- detail::enable_if_t<std::is_nothrow_constructible<
- T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- void emplace(std::initializer_list<U> il, Args &&... args) {
- if (has_value()) {
- T t(il, std::forward<Args>(args)...);
- val() = std::move(t);
- } else {
- err().~unexpected<E>();
- ::new (valptr()) T(il, std::forward<Args>(args)...);
- this->m_has_val = true;
- }
- }
-
- template <class U, class... Args,
- detail::enable_if_t<!std::is_nothrow_constructible<
- T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
- void emplace(std::initializer_list<U> il, Args &&... args) {
- if (has_value()) {
- T t(il, std::forward<Args>(args)...);
- val() = std::move(t);
- } else {
- auto tmp = std::move(err());
- err().~unexpected<E>();
-
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- try {
- ::new (valptr()) T(il, std::forward<Args>(args)...);
- this->m_has_val = true;
- } catch (...) {
- err() = std::move(tmp);
- throw;
- }
- #else
- ::new (valptr()) T(il, std::forward<Args>(args)...);
- this->m_has_val = true;
- #endif
- }
- }
-
- private:
- using t_is_void = std::true_type;
- using t_is_not_void = std::false_type;
- using t_is_nothrow_move_constructible = std::true_type;
- using move_constructing_t_can_throw = std::false_type;
- using e_is_nothrow_move_constructible = std::true_type;
- using move_constructing_e_can_throw = std::false_type;
-
- void swap_where_both_have_value(expected &/*rhs*/ , t_is_void) noexcept {
- // swapping void is a no-op
- }
-
- void swap_where_both_have_value(expected &rhs, t_is_not_void) {
- using std::swap;
- swap(val(), rhs.val());
- }
-
- void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
- std::is_nothrow_move_constructible<E>::value) {
- ::new (errptr()) unexpected_type(std::move(rhs.err()));
- rhs.err().~unexpected_type();
- std::swap(this->m_has_val, rhs.m_has_val);
- }
-
- void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
- swap_where_only_one_has_value_and_t_is_not_void(
- rhs, typename std::is_nothrow_move_constructible<T>::type{},
- typename std::is_nothrow_move_constructible<E>::type{});
- }
-
- void swap_where_only_one_has_value_and_t_is_not_void(
- expected &rhs, t_is_nothrow_move_constructible,
- e_is_nothrow_move_constructible) noexcept {
- auto temp = std::move(val());
- val().~T();
- ::new (errptr()) unexpected_type(std::move(rhs.err()));
- rhs.err().~unexpected_type();
- ::new (rhs.valptr()) T(std::move(temp));
- std::swap(this->m_has_val, rhs.m_has_val);
- }
-
- void swap_where_only_one_has_value_and_t_is_not_void(
- expected &rhs, t_is_nothrow_move_constructible,
- move_constructing_e_can_throw) {
- auto temp = std::move(val());
- val().~T();
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- try {
- ::new (errptr()) unexpected_type(std::move(rhs.err()));
- rhs.err().~unexpected_type();
- ::new (rhs.valptr()) T(std::move(temp));
- std::swap(this->m_has_val, rhs.m_has_val);
- } catch (...) {
- val() = std::move(temp);
- throw;
- }
- #else
- ::new (errptr()) unexpected_type(std::move(rhs.err()));
- rhs.err().~unexpected_type();
- ::new (rhs.valptr()) T(std::move(temp));
- std::swap(this->m_has_val, rhs.m_has_val);
- #endif
- }
-
- void swap_where_only_one_has_value_and_t_is_not_void(
- expected &rhs, move_constructing_t_can_throw,
- t_is_nothrow_move_constructible) {
- auto temp = std::move(rhs.err());
- rhs.err().~unexpected_type();
- #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
- try {
- ::new (rhs.valptr()) T(val());
- val().~T();
- ::new (errptr()) unexpected_type(std::move(temp));
- std::swap(this->m_has_val, rhs.m_has_val);
- } catch (...) {
- rhs.err() = std::move(temp);
- throw;
- }
- #else
- ::new (rhs.valptr()) T(val());
- val().~T();
- ::new (errptr()) unexpected_type(std::move(temp));
- std::swap(this->m_has_val, rhs.m_has_val);
- #endif
- }
-
- public:
- template <class OT = T, class OE = E>
- detail::enable_if_t<detail::is_swappable<OT>::value &&
- detail::is_swappable<OE>::value &&
- (std::is_nothrow_move_constructible<OT>::value ||
- std::is_nothrow_move_constructible<OE>::value)>
- swap(expected &rhs) noexcept(
- std::is_nothrow_move_constructible<T>::value
- &&detail::is_nothrow_swappable<T>::value
- &&std::is_nothrow_move_constructible<E>::value
- &&detail::is_nothrow_swappable<E>::value) {
- if (has_value() && rhs.has_value()) {
- swap_where_both_have_value(rhs, typename std::is_void<T>::type{});
- } else if (!has_value() && rhs.has_value()) {
- rhs.swap(*this);
- } else if (has_value()) {
- swap_where_only_one_has_value(rhs, typename std::is_void<T>::type{});
- } else {
- using std::swap;
- swap(err(), rhs.err());
- }
- }
-
- constexpr const T *operator->() const { return valptr(); }
- TL_EXPECTED_11_CONSTEXPR T *operator->() { return valptr(); }
-
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- constexpr const U &operator*() const & {
- return val();
- }
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR U &operator*() & {
- return val();
- }
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- constexpr const U &&operator*() const && {
- return std::move(val());
- }
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR U &&operator*() && {
- return std::move(val());
- }
-
- constexpr bool has_value() const noexcept { return this->m_has_val; }
- constexpr explicit operator bool() const noexcept { return this->m_has_val; }
-
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR const U &value() const & {
- if (!has_value())
- detail::throw_exception(bad_expected_access<E>(err().value()));
- return val();
- }
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR U &value() & {
- if (!has_value())
- detail::throw_exception(bad_expected_access<E>(err().value()));
- return val();
- }
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR const U &&value() const && {
- if (!has_value())
- detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
- return std::move(val());
- }
- template <class U = T,
- detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
- TL_EXPECTED_11_CONSTEXPR U &&value() && {
- if (!has_value())
- detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
- return std::move(val());
- }
-
- constexpr const E &error() const & { return err().value(); }
- TL_EXPECTED_11_CONSTEXPR E &error() & { return err().value(); }
- constexpr const E &&error() const && { return std::move(err().value()); }
- TL_EXPECTED_11_CONSTEXPR E &&error() && { return std::move(err().value()); }
-
- template <class U> constexpr T value_or(U &&v) const & {
- static_assert(std::is_copy_constructible<T>::value &&
- std::is_convertible<U &&, T>::value,
- "T must be copy-constructible and convertible to from U&&");
- return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
- }
- template <class U> TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && {
- static_assert(std::is_move_constructible<T>::value &&
- std::is_convertible<U &&, T>::value,
- "T must be move-constructible and convertible to from U&&");
- return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
- }
- };
-
- namespace detail {
- template <class Exp> using exp_t = typename detail::decay_t<Exp>::value_type;
- template <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;
- template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
-
- #ifdef TL_EXPECTED_CXX14
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- *std::declval<Exp>()))>
- constexpr auto and_then_impl(Exp &&exp, F &&f) {
- static_assert(detail::is_expected<Ret>::value, "F must return an expected");
-
- return exp.has_value()
- ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
- : Ret(unexpect, std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>()))>
- constexpr auto and_then_impl(Exp &&exp, F &&f) {
- static_assert(detail::is_expected<Ret>::value, "F must return an expected");
-
- return exp.has_value() ? detail::invoke(std::forward<F>(f))
- : Ret(unexpect, std::forward<Exp>(exp).error());
- }
- #else
- template <class> struct TC;
- template <class Exp, class F,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- *std::declval<Exp>())),
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
- auto and_then_impl(Exp &&exp, F &&f) -> Ret {
- static_assert(detail::is_expected<Ret>::value, "F must return an expected");
-
- return exp.has_value()
- ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
- : Ret(unexpect, std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- class Ret = decltype(detail::invoke(std::declval<F>())),
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
- constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
- static_assert(detail::is_expected<Ret>::value, "F must return an expected");
-
- return exp.has_value() ? detail::invoke(std::forward<F>(f))
- : Ret(unexpect, std::forward<Exp>(exp).error());
- }
- #endif
-
- #ifdef TL_EXPECTED_CXX14
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- *std::declval<Exp>())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- constexpr auto expected_map_impl(Exp &&exp, F &&f) {
- using result = ret_t<Exp, detail::decay_t<Ret>>;
- return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
- *std::forward<Exp>(exp)))
- : result(unexpect, std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- *std::declval<Exp>())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- auto expected_map_impl(Exp &&exp, F &&f) {
- using result = expected<void, err_t<Exp>>;
- if (exp.has_value()) {
- detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
- return result();
- }
-
- return result(unexpect, std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- constexpr auto expected_map_impl(Exp &&exp, F &&f) {
- using result = ret_t<Exp, detail::decay_t<Ret>>;
- return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
- : result(unexpect, std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- auto expected_map_impl(Exp &&exp, F &&f) {
- using result = expected<void, err_t<Exp>>;
- if (exp.has_value()) {
- detail::invoke(std::forward<F>(f));
- return result();
- }
-
- return result(unexpect, std::forward<Exp>(exp).error());
- }
- #else
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- *std::declval<Exp>())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
-
- constexpr auto expected_map_impl(Exp &&exp, F &&f)
- -> ret_t<Exp, detail::decay_t<Ret>> {
- using result = ret_t<Exp, detail::decay_t<Ret>>;
-
- return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
- *std::forward<Exp>(exp)))
- : result(unexpect, std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- *std::declval<Exp>())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
-
- auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
- if (exp.has_value()) {
- detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
- return {};
- }
-
- return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
-
- constexpr auto expected_map_impl(Exp &&exp, F &&f)
- -> ret_t<Exp, detail::decay_t<Ret>> {
- using result = ret_t<Exp, detail::decay_t<Ret>>;
-
- return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
- : result(unexpect, std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
-
- auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
- if (exp.has_value()) {
- detail::invoke(std::forward<F>(f));
- return {};
- }
-
- return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
- }
- #endif
-
- #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
- !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- constexpr auto map_error_impl(Exp &&exp, F &&f) {
- using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
- return exp.has_value()
- ? result(*std::forward<Exp>(exp))
- : result(unexpect, detail::invoke(std::forward<F>(f),
- std::forward<Exp>(exp).error()));
- }
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- auto map_error_impl(Exp &&exp, F &&f) {
- using result = expected<exp_t<Exp>, monostate>;
- if (exp.has_value()) {
- return result(*std::forward<Exp>(exp));
- }
-
- detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
- return result(unexpect, monostate{});
- }
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- constexpr auto map_error_impl(Exp &&exp, F &&f) {
- using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
- return exp.has_value()
- ? result()
- : result(unexpect, detail::invoke(std::forward<F>(f),
- std::forward<Exp>(exp).error()));
- }
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- auto map_error_impl(Exp &&exp, F &&f) {
- using result = expected<exp_t<Exp>, monostate>;
- if (exp.has_value()) {
- return result();
- }
-
- detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
- return result(unexpect, monostate{});
- }
- #else
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- constexpr auto map_error_impl(Exp &&exp, F &&f)
- -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
- using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
-
- return exp.has_value()
- ? result(*std::forward<Exp>(exp))
- : result(unexpect, detail::invoke(std::forward<F>(f),
- std::forward<Exp>(exp).error()));
- }
-
- template <class Exp, class F,
- detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
- using result = expected<exp_t<Exp>, monostate>;
- if (exp.has_value()) {
- return result(*std::forward<Exp>(exp));
- }
-
- detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
- return result(unexpect, monostate{});
- }
-
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- constexpr auto map_error_impl(Exp &&exp, F &&f)
- -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
- using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
-
- return exp.has_value()
- ? result()
- : result(unexpect, detail::invoke(std::forward<F>(f),
- std::forward<Exp>(exp).error()));
- }
-
- template <class Exp, class F,
- detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
- using result = expected<exp_t<Exp>, monostate>;
- if (exp.has_value()) {
- return result();
- }
-
- detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
- return result(unexpect, monostate{});
- }
- #endif
-
- #ifdef TL_EXPECTED_CXX14
- template <class Exp, class F,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- constexpr auto or_else_impl(Exp &&exp, F &&f) {
- static_assert(detail::is_expected<Ret>::value, "F must return an expected");
- return exp.has_value()
- ? std::forward<Exp>(exp)
- : detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
- return exp.has_value()
- ? std::forward<Exp>(exp)
- : (detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()),
- std::forward<Exp>(exp));
- }
- #else
- template <class Exp, class F,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
- auto or_else_impl(Exp &&exp, F &&f) -> Ret {
- static_assert(detail::is_expected<Ret>::value, "F must return an expected");
- return exp.has_value()
- ? std::forward<Exp>(exp)
- : detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
- }
-
- template <class Exp, class F,
- class Ret = decltype(detail::invoke(std::declval<F>(),
- std::declval<Exp>().error())),
- detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
- detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
- return exp.has_value()
- ? std::forward<Exp>(exp)
- : (detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()),
- std::forward<Exp>(exp));
- }
- #endif
- } // namespace detail
-
- template <class T, class E, class U, class F>
- constexpr bool operator==(const expected<T, E> &lhs,
- const expected<U, F> &rhs) {
- return (lhs.has_value() != rhs.has_value())
- ? false
- : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
- }
- template <class T, class E, class U, class F>
- constexpr bool operator!=(const expected<T, E> &lhs,
- const expected<U, F> &rhs) {
- return (lhs.has_value() != rhs.has_value())
- ? true
- : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
- }
-
- template <class T, class E, class U>
- constexpr bool operator==(const expected<T, E> &x, const U &v) {
- return x.has_value() ? *x == v : false;
- }
- template <class T, class E, class U>
- constexpr bool operator==(const U &v, const expected<T, E> &x) {
- return x.has_value() ? *x == v : false;
- }
- template <class T, class E, class U>
- constexpr bool operator!=(const expected<T, E> &x, const U &v) {
- return x.has_value() ? *x != v : true;
- }
- template <class T, class E, class U>
- constexpr bool operator!=(const U &v, const expected<T, E> &x) {
- return x.has_value() ? *x != v : true;
- }
-
- template <class T, class E>
- constexpr bool operator==(const expected<T, E> &x, const unexpected<E> &e) {
- return x.has_value() ? false : x.error() == e.value();
- }
- template <class T, class E>
- constexpr bool operator==(const unexpected<E> &e, const expected<T, E> &x) {
- return x.has_value() ? false : x.error() == e.value();
- }
- template <class T, class E>
- constexpr bool operator!=(const expected<T, E> &x, const unexpected<E> &e) {
- return x.has_value() ? true : x.error() != e.value();
- }
- template <class T, class E>
- constexpr bool operator!=(const unexpected<E> &e, const expected<T, E> &x) {
- return x.has_value() ? true : x.error() != e.value();
- }
-
- template <class T, class E,
- detail::enable_if_t<(std::is_void<T>::value ||
- std::is_move_constructible<T>::value) &&
- detail::is_swappable<T>::value &&
- std::is_move_constructible<E>::value &&
- detail::is_swappable<E>::value> * = nullptr>
- void swap(expected<T, E> &lhs,
- expected<T, E> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
- lhs.swap(rhs);
- }
- } // namespace tl
-
- #endif
|