File indexing completed on 2025-02-16 05:12:21

0001 ////////////////////////////////////////////////////////////////////////////////
0002 /// \file result.hpp
0003 ///
0004 /// \brief This header contains the 'result' monadic type for indicating
0005 ///        possible error conditions
0006 ////////////////////////////////////////////////////////////////////////////////
0007 
0008 /*
0009   The MIT License (MIT)
0010 
0011   Copyright (c) 2017-2021 Matthew Rodusek All rights reserved.
0012 
0013   Permission is hereby granted, free of charge, to any person obtaining a copy
0014   of this software and associated documentation files (the "Software"), to deal
0015   in the Software without restriction, including without limitation the rights
0016   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0017   copies of the Software, and to permit persons to whom the Software is
0018   furnished to do so, subject to the following conditions:
0019 
0020   The above copyright notice and this permission notice shall be included in
0021   all copies or substantial portions of the Software.
0022 
0023   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0024   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0025   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0026   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0027   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0028   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0029   SOFTWARE.
0030 */
0031 
0032 #ifndef RESULT_RESULT_HPP
0033 #define RESULT_RESULT_HPP
0034 
0035 #include <cstddef> // std::size_t
0036 #include <functional> // std::reference_wrapper, std::invoke
0037 #include <initializer_list> // std::initializer_list
0038 #include <memory> // std::address_of
0039 #include <new> // placement-new
0040 #include <string> // std::string (for exception message)
0041 #include <type_traits> // std::enable_if, std::is_constructible, etc
0042 #include <utility> // std::in_place_t, std::forward
0043 
0044 #if defined(RESULT_EXCEPTIONS_DISABLED)
0045 #include <cstdio> // std::fprintf, stderr
0046 #else
0047 #include <stdexcept> // std::logic_error
0048 #endif
0049 
0050 #if __cplusplus >= 201402L
0051 #define RESULT_CPP14_CONSTEXPR constexpr
0052 #else
0053 #define RESULT_CPP14_CONSTEXPR
0054 #endif
0055 
0056 #if __cplusplus >= 201703L
0057 #define RESULT_CPP17_INLINE inline
0058 #else
0059 #define RESULT_CPP17_INLINE
0060 #endif
0061 
0062 #if defined(__clang__) && defined(_MSC_VER)
0063 #define RESULT_INLINE_VISIBILITY __attribute__((visibility("hidden")))
0064 #elif defined(__clang__) || defined(__GNUC__)
0065 #define RESULT_INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline))
0066 #elif defined(_MSC_VER)
0067 #define RESULT_INLINE_VISIBILITY __forceinline
0068 #else
0069 #define RESULT_INLINE_VISIBILITY
0070 #endif
0071 
0072 // [[clang::warn_unused_result]] is more full-featured than gcc's variant, since
0073 // it supports being applied to class objects.
0074 #if __cplusplus >= 201703L
0075 #define RESULT_NODISCARD [[nodiscard]]
0076 #define RESULT_WARN_UNUSED [[nodiscard]]
0077 #elif defined(__clang__) && ((__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ >= 9)))
0078 #define RESULT_NODISCARD [[clang::warn_unused_result]]
0079 #define RESULT_WARN_UNUSED [[clang::warn_unused_result]]
0080 #elif defined(__GNUC__)
0081 #define RESULT_NODISCARD
0082 #define RESULT_WARN_UNUSED [[gnu::warn_unused_result]]
0083 #else
0084 #define RESULT_WARN_UNUSED
0085 #define RESULT_NODISCARD
0086 #endif
0087 
0088 #if defined(RESULT_NAMESPACE)
0089 #define RESULT_NAMESPACE_INTERNAL RESULT_NAMESPACE
0090 #else
0091 #define RESULT_NAMESPACE_INTERNAL cpp
0092 #endif
0093 #define RESULT_NS_IMPL RESULT_NAMESPACE_INTERNAL::bitwizeshift
0094 
0095 // clang's `-Wdocumentation-unknown-command` flag is bugged and does not
0096 // understand `\copydoc` tags, despite this being a valid doxygen tag.
0097 #if defined(__clang__)
0098 #pragma clang diagnostic push
0099 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
0100 #endif
0101 
0102 namespace RESULT_NAMESPACE_INTERNAL {
0103 inline namespace bitwizeshift {
0104 
0105 //===========================================================================
0106 // utilities : constexpr forward
0107 //===========================================================================
0108 
0109 // std::forward is not constexpr until C++14
0110 namespace detail {
0111 #if __cplusplus >= 201402L
0112 using std::forward;
0113 #else
0114 template<typename T>
0115 inline RESULT_INLINE_VISIBILITY constexpr auto forward(typename std::remove_reference<T>::type& t) noexcept -> T&&
0116 {
0117     return static_cast<T&&>(t);
0118 }
0119 
0120 template<typename T>
0121 inline RESULT_INLINE_VISIBILITY constexpr auto forward(typename std::remove_reference<T>::type&& t) noexcept -> T&&
0122 {
0123     return static_cast<T&&>(t);
0124 }
0125 #endif
0126 } // namespace detail
0127 
0128 //===========================================================================
0129 // utilities : invoke / invoke_result
0130 //===========================================================================
0131 
0132 // std::invoke was introduced in C++17
0133 
0134 namespace detail {
0135 #if __cplusplus >= 201703L
0136 using std::invoke;
0137 using std::invoke_result;
0138 using std::invoke_result_t;
0139 #else
0140 template<typename T>
0141 struct is_reference_wrapper : std::false_type {
0142 };
0143 
0144 template<typename U>
0145 struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {
0146 };
0147 
0148 //-------------------------------------------------------------------------
0149 
0150 template<typename Base,
0151          typename T,
0152          typename Derived,
0153          typename... Args,
0154          typename = typename std::enable_if<std::is_function<T>::value
0155                                             && std::is_base_of<Base, typename std::decay<Derived>::type>::value>::type>
0156 inline RESULT_INLINE_VISIBILITY constexpr auto invoke(T Base::*pmf, Derived&& ref, Args&&...args) noexcept(
0157     noexcept((::RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmf)(::RESULT_NS_IMPL::detail::forward<Args>(args)...)))
0158     -> decltype((::RESULT_NS_IMPL::detail::forward<Derived>(ref)
0159                  .*pmf)(::RESULT_NS_IMPL::detail::forward<Args>(args)...))
0160 {
0161     return (RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
0162 }
0163 
0164 template<typename Base,
0165          typename T,
0166          typename RefWrap,
0167          typename... Args,
0168          typename = typename std::enable_if<std::is_function<T>::value
0169                                             && is_reference_wrapper<typename std::decay<RefWrap>::type>::value>::type>
0170 inline RESULT_INLINE_VISIBILITY constexpr auto
0171 invoke(T Base::*pmf, RefWrap&& ref, Args&&...args) noexcept(noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
0172     -> decltype((ref.get().*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...))
0173 {
0174     return (ref.get().*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
0175 }
0176 
0177 template<typename Base,
0178          typename T,
0179          typename Pointer,
0180          typename... Args,
0181          typename = typename std::enable_if<std::is_function<T>::value
0182                                             && !is_reference_wrapper<typename std::decay<Pointer>::type>::value
0183                                             && !std::is_base_of<Base, typename std::decay<Pointer>::type>::value>::type>
0184 inline RESULT_INLINE_VISIBILITY constexpr auto invoke(T Base::*pmf, Pointer&& ptr, Args&&...args) noexcept(
0185     noexcept(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)))
0186     -> decltype(((*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...))
0187 {
0188     return ((*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
0189 }
0190 
0191 template<typename Base,
0192          typename T,
0193          typename Derived,
0194          typename = typename std::enable_if<!std::is_function<T>::value
0195                                             && std::is_base_of<Base, typename std::decay<Derived>::type>::value>::type>
0196 inline RESULT_INLINE_VISIBILITY constexpr auto invoke(T Base::*pmd,
0197                                                       Derived&& ref) noexcept(noexcept(std::forward<Derived>(ref).*pmd))
0198     -> decltype(RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmd)
0199 {
0200     return RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmd;
0201 }
0202 
0203 template<typename Base,
0204          typename T,
0205          typename RefWrap,
0206          typename = typename std::enable_if<!std::is_function<T>::value
0207                                             && is_reference_wrapper<typename std::decay<RefWrap>::type>::value>::type>
0208 inline RESULT_INLINE_VISIBILITY constexpr auto invoke(T Base::*pmd, RefWrap&& ref) noexcept(noexcept(ref.get().*pmd))
0209     -> decltype(ref.get().*pmd)
0210 {
0211     return ref.get().*pmd;
0212 }
0213 
0214 template<typename Base,
0215          typename T,
0216          typename Pointer,
0217          typename = typename std::enable_if<!std::is_function<T>::value
0218                                             && !is_reference_wrapper<typename std::decay<Pointer>::type>::value
0219                                             && !std::is_base_of<Base, typename std::decay<Pointer>::type>::value>::type>
0220 inline RESULT_INLINE_VISIBILITY constexpr auto
0221 invoke(T Base::*pmd, Pointer&& ptr) noexcept(noexcept((*std::forward<Pointer>(ptr)).*pmd))
0222     -> decltype((*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmd)
0223 {
0224     return (*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmd;
0225 }
0226 
0227 template<typename F,
0228          typename... Args,
0229          typename = typename std::enable_if<!std::is_member_pointer<typename std::decay<F>::type>::value>::type>
0230 inline RESULT_INLINE_VISIBILITY constexpr auto
0231 invoke(F&& f, Args&&...args) noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
0232     -> decltype(RESULT_NS_IMPL::detail::forward<F>(f)(RESULT_NS_IMPL::detail::forward<Args>(args)...))
0233 {
0234     return RESULT_NS_IMPL::detail::forward<F>(f)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
0235 }
0236 
0237 template<typename Fn, typename... Args>
0238 struct is_invocable {
0239     template<typename Fn2, typename... Args2>
0240     static auto test(Fn2&&, Args2&&...)
0241         -> decltype(invoke(std::declval<Fn2>(), std::declval<Args2>()...), std::true_type{});
0242 
0243     static auto test(...) -> std::false_type;
0244 
0245     using type = decltype(test(std::declval<Fn>(), std::declval<Args>()...));
0246     static constexpr bool value = type::value;
0247 };
0248 
0249 template<bool B, typename Fn, typename... Args>
0250 struct invoke_result_impl {
0251     using type = decltype(RESULT_NS_IMPL::detail::invoke(std::declval<Fn>(), std::declval<Args>()...));
0252 };
0253 template<typename Fn, typename... Args>
0254 struct invoke_result_impl<false, Fn, Args...> {
0255 };
0256 
0257 template<typename Fn, typename... Args>
0258 struct invoke_result : invoke_result_impl<is_invocable<Fn, Args...>::value, Fn, Args...> {
0259 };
0260 
0261 template<typename Fn, typename... Args>
0262 using invoke_result_t = typename invoke_result<Fn, Args...>::type;
0263 #endif
0264 } // namespace detail
0265 
0266 //===========================================================================
0267 // struct : in_place_t
0268 //===========================================================================
0269 
0270 #if __cplusplus >= 201703L
0271 using std::in_place;
0272 using std::in_place_t;
0273 #else
0274 /// \brief A structure for representing in-place construction
0275 struct in_place_t {
0276     explicit in_place_t() = default;
0277 };
0278 RESULT_CPP17_INLINE constexpr auto in_place = in_place_t{};
0279 #endif
0280 
0281 //===========================================================================
0282 // struct : in_place_t
0283 //===========================================================================
0284 
0285 /// \brief A structure for representing in-place construction of an error type
0286 struct in_place_error_t {
0287     explicit in_place_error_t() = default;
0288 };
0289 
0290 RESULT_CPP17_INLINE constexpr auto in_place_error = in_place_error_t{};
0291 
0292 //===========================================================================
0293 // forward-declarations
0294 //===========================================================================
0295 
0296 template<typename>
0297 class failure;
0298 
0299 template<typename, typename>
0300 class result;
0301 
0302 template<typename>
0303 class bad_result_access;
0304 
0305 //===========================================================================
0306 // traits
0307 //===========================================================================
0308 
0309 template<typename T>
0310 struct is_failure : std::false_type {
0311 };
0312 template<typename E>
0313 struct is_failure<failure<E>> : std::true_type {
0314 };
0315 
0316 template<typename T>
0317 struct is_result : std::false_type {
0318 };
0319 template<typename T, typename E>
0320 struct is_result<result<T, E>> : std::true_type {
0321 };
0322 
0323 //===========================================================================
0324 // trait : detail::wrapped_result_type
0325 //===========================================================================
0326 
0327 namespace detail {
0328 
0329 template<typename T>
0330 using wrapped_result_type = typename std::conditional<std::is_lvalue_reference<T>::value,
0331                                                       std::reference_wrapper<typename std::remove_reference<T>::type>,
0332                                                       typename std::remove_const<T>::type>::type;
0333 
0334 } // namespace detail
0335 
0336 #if !defined(RESULT_DISABLE_EXCEPTIONS)
0337 
0338 //===========================================================================
0339 // class : bad_result_access<E>
0340 //===========================================================================
0341 
0342 /////////////////////////////////////////////////////////////////////////////
0343 /// \brief An exception thrown when result::value is accessed without
0344 ///        a contained value
0345 /////////////////////////////////////////////////////////////////////////////
0346 template<typename E>
0347 class bad_result_access : public std::logic_error {
0348     //-------------------------------------------------------------------------
0349     // Constructor / Assignment
0350     //-------------------------------------------------------------------------
0351   public:
0352     /// \brief Constructs this exception using the underlying error type for
0353     ///        the error type
0354     ///
0355     /// \param error the underlying error
0356     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, E2>::value>::type>
0357     explicit bad_result_access(E2&& error);
0358 
0359     /// \{
0360     /// \brief Constructs this exception using the underlying error type for
0361     ///        the error and a message
0362     ///
0363     /// \param what_arg the message for the failure
0364     /// \param error the underlying error
0365     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, E2>::value>::type>
0366     bad_result_access(const char *what_arg, E2&& error);
0367     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, E2>::value>::type>
0368     bad_result_access(const std::string& what_arg, E2&& error);
0369     /// \}
0370 
0371     bad_result_access(const bad_result_access& other) = default;
0372     bad_result_access(bad_result_access&& other) = default;
0373 
0374     //-------------------------------------------------------------------------
0375 
0376     auto operator=(const bad_result_access& other) -> bad_result_access& = default;
0377     auto operator=(bad_result_access&& other) -> bad_result_access& = default;
0378 
0379     /// \{
0380     /// \brief Gets the underlying error
0381     ///
0382     /// \return the error
0383     auto error() & noexcept -> E&;
0384     auto error() && noexcept -> E&&;
0385     auto error() const& noexcept -> const E&;
0386     auto error() const&& noexcept -> const E&&;
0387     /// \}
0388 
0389     //-------------------------------------------------------------------------
0390     // Private Members
0391     //-------------------------------------------------------------------------
0392   private:
0393     E m_error;
0394 };
0395 
0396 #endif
0397 
0398 namespace detail {
0399 
0400 template<typename E, typename E2>
0401 using failure_is_value_convertible = std::integral_constant<
0402     bool,
0403     (std::is_constructible<E, E2&&>::value && !std::is_same<typename std::decay<E2>::type, in_place_t>::value
0404      && !is_failure<typename std::decay<E2>::type>::value && !is_result<typename std::decay<E2>::type>::value)>;
0405 
0406 template<typename E, typename E2>
0407 using failure_is_explicit_value_convertible =
0408     std::integral_constant<bool, (failure_is_value_convertible<E, E2>::value && !std::is_convertible<E2, E>::value)>;
0409 
0410 template<typename E, typename E2>
0411 using failure_is_implicit_value_convertible =
0412     std::integral_constant<bool, (failure_is_value_convertible<E, E2>::value && std::is_convertible<E2, E>::value)>;
0413 
0414 template<typename E, typename E2>
0415 using failure_is_value_assignable = std::integral_constant<bool,
0416                                                            (!is_result<typename std::decay<E2>::type>::value
0417                                                             && !is_failure<typename std::decay<E2>::type>::value
0418                                                             && std::is_assignable<wrapped_result_type<E>&, E2>::value)>;
0419 
0420 } // namespace detail
0421 
0422 //===========================================================================
0423 // class : failure_type
0424 //===========================================================================
0425 
0426 //////////////////////////////////////////////////////////////////////////////
0427 /// \brief A semantic type used for distinguishing failure values in an
0428 ///        API that returns result types
0429 ///
0430 /// \tparam E the error type
0431 //////////////////////////////////////////////////////////////////////////////
0432 template<typename E>
0433 class failure {
0434     static_assert(!is_result<typename std::decay<E>::type>::value,
0435                   "A (possibly CV-qualified) result 'E' type is ill-formed.");
0436     static_assert(!is_failure<typename std::decay<E>::type>::value,
0437                   "A (possibly CV-qualified) failure 'E' type is ill-formed.");
0438     static_assert(!std::is_void<typename std::decay<E>::type>::value,
0439                   "A (possibly CV-qualified) 'void' 'E' type is ill-formed.");
0440     static_assert(!std::is_rvalue_reference<E>::value,
0441                   "rvalue references for 'E' type is ill-formed. "
0442                   "Only lvalue references are valid.");
0443 
0444     //-------------------------------------------------------------------------
0445     // Public Member Types
0446     //-------------------------------------------------------------------------
0447   public:
0448     using error_type = E;
0449 
0450     //-------------------------------------------------------------------------
0451     // Constructors / Assignment
0452     //-------------------------------------------------------------------------
0453   public:
0454     /// \brief Constructs a failure via default construction
0455     failure() = default;
0456 
0457     /// \brief Constructs a failure by delegating construction to the
0458     ///        underlying constructor
0459     ///
0460     /// \param args the arguments to forward to E's constructor
0461     template<typename... Args, typename = typename std::enable_if<std::is_constructible<E, Args...>::value>::type>
0462     constexpr failure(in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value);
0463 
0464     /// \brief Constructs a failure by delegating construction to the
0465     ///        underlying constructor
0466     ///
0467     /// \param ilist the initializer list
0468     /// \param args the arguments to forward to E's constructor
0469     template<
0470         typename U,
0471         typename... Args,
0472         typename = typename std::enable_if<std::is_constructible<E, std::initializer_list<U>, Args...>::value>::type>
0473     constexpr failure(in_place_t, std::initializer_list<U> ilist, Args&&...args) noexcept(
0474         std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value);
0475 
0476     /// \{
0477     /// \brief Constructs a failure from the given error
0478     ///
0479     /// \param error the error to create a failure from
0480     template<typename E2,
0481              typename std::enable_if<detail::failure_is_implicit_value_convertible<E, E2>::value, int>::type = 0>
0482     constexpr failure(E2&& error) noexcept(std::is_nothrow_constructible<E, E2>::value);
0483     template<typename E2,
0484              typename std::enable_if<detail::failure_is_explicit_value_convertible<E, E2>::value, int>::type = 0>
0485     constexpr explicit failure(E2&& error) noexcept(std::is_nothrow_constructible<E, E2>::value);
0486     /// \}
0487 
0488     /// \brief Constructs this failure by copying the contents of an existing
0489     ///        one
0490     ///
0491     /// \param other the other failure to copy
0492     /* implicit */ failure(const failure& other) = default;
0493 
0494     /// \brief Constructs this failure by moving the contents of an existing
0495     ///        one
0496     ///
0497     /// \param other the other failure to move
0498     /* implicit */ failure(failure&& other) = default;
0499 
0500     /// \brief Constructs this failure by copy-converting \p other
0501     ///
0502     /// \param other the other failure to copy
0503     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, const E2&>::value>::type>
0504     constexpr /* implicit */ failure(const failure<E2>& other) noexcept(
0505         std::is_nothrow_constructible<E, const E2&>::value);
0506 
0507     /// \brief Constructs this failure by move-converting \p other
0508     ///
0509     /// \param other the other failure to copy
0510     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, E2&&>::value>::type>
0511     constexpr /* implicit */ failure(failure<E2>&& other) noexcept(std::is_nothrow_constructible<E, E2&&>::value);
0512 
0513     //--------------------------------------------------------------------------
0514 
0515     /// \brief Assigns the value of \p error to this failure through
0516     ///        move-assignment
0517     ///
0518     /// \param error the value to assign
0519     /// \return reference to `(*this)`
0520     template<typename E2, typename = typename std::enable_if<detail::failure_is_value_assignable<E, E2>::value>::type>
0521     RESULT_CPP14_CONSTEXPR auto operator=(E2&& error) noexcept(std::is_nothrow_assignable<E, E2>::value
0522                                                                || std::is_lvalue_reference<E>::value) -> failure&;
0523 
0524     /// \brief Assigns the contents of \p other to this by copy-assignment
0525     ///
0526     /// \param other the other failure to copy
0527     /// \return reference to `(*this)`
0528     auto operator=(const failure& other) -> failure& = default;
0529 
0530     /// \brief Assigns the contents of \p other to this by move-assignment
0531     ///
0532     /// \param other the other failure to move
0533     /// \return reference to `(*this)`
0534     auto operator=(failure&& other) -> failure& = default;
0535 
0536     /// \brief Assigns the contents of \p other to this by copy conversion
0537     ///
0538     /// \param other the other failure to copy-convert
0539     /// \return reference to `(*this)`
0540     template<typename E2, typename = typename std::enable_if<std::is_assignable<E&, const E2&>::value>::type>
0541     RESULT_CPP14_CONSTEXPR auto
0542     operator=(const failure<E2>& other) noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> failure&;
0543 
0544     /// \brief Assigns the contents of \p other to this by move conversion
0545     ///
0546     /// \param other the other failure to move-convert
0547     /// \return reference to `(*this)`
0548     template<typename E2, typename = typename std::enable_if<std::is_assignable<E&, E2&&>::value>::type>
0549     RESULT_CPP14_CONSTEXPR auto operator=(failure<E2>&& other) noexcept(std::is_nothrow_assignable<E, E2&&>::value)
0550         -> failure&;
0551 
0552     //--------------------------------------------------------------------------
0553     // Observers
0554     //--------------------------------------------------------------------------
0555   public:
0556     /// \{
0557     /// \brief Gets the underlying error
0558     ///
0559     /// \return the underlying error
0560     RESULT_CPP14_CONSTEXPR
0561     auto error() & noexcept -> typename std::add_lvalue_reference<E>::type;
0562     RESULT_CPP14_CONSTEXPR
0563     auto error() && noexcept -> typename std::add_rvalue_reference<E>::type;
0564     constexpr auto error() const& noexcept ->
0565         typename std::add_lvalue_reference<typename std::add_const<E>::type>::type;
0566     constexpr auto error() const&& noexcept ->
0567         typename std::add_rvalue_reference<typename std::add_const<E>::type>::type;
0568     /// \}
0569 
0570     //-------------------------------------------------------------------------
0571     // Private Member Types
0572     //-------------------------------------------------------------------------
0573   private:
0574     using underlying_type = detail::wrapped_result_type<E>;
0575 
0576     //-------------------------------------------------------------------------
0577     // Private Members
0578     //-------------------------------------------------------------------------
0579   private:
0580     underlying_type m_failure;
0581 };
0582 
0583 #if __cplusplus >= 201703L
0584 template<typename T>
0585 failure(std::reference_wrapper<T>) -> failure<T&>;
0586 
0587 template<typename T>
0588 failure(T&&) -> failure<typename std::decay<T>::type>;
0589 #endif
0590 
0591 //===========================================================================
0592 // non-member functions : class : failure
0593 //===========================================================================
0594 
0595 //---------------------------------------------------------------------------
0596 // Comparison
0597 //---------------------------------------------------------------------------
0598 
0599 template<typename E1, typename E2>
0600 constexpr auto operator==(const failure<E1>& lhs, const failure<E2>& rhs) noexcept -> bool;
0601 template<typename E1, typename E2>
0602 constexpr auto operator!=(const failure<E1>& lhs, const failure<E2>& rhs) noexcept -> bool;
0603 template<typename E1, typename E2>
0604 constexpr auto operator<(const failure<E1>& lhs, const failure<E2>& rhs) noexcept -> bool;
0605 template<typename E1, typename E2>
0606 constexpr auto operator>(const failure<E1>& lhs, const failure<E2>& rhs) noexcept -> bool;
0607 template<typename E1, typename E2>
0608 constexpr auto operator<=(const failure<E1>& lhs, const failure<E2>& rhs) noexcept -> bool;
0609 template<typename E1, typename E2>
0610 constexpr auto operator>=(const failure<E1>& lhs, const failure<E2>& rhs) noexcept -> bool;
0611 
0612 //---------------------------------------------------------------------------
0613 // Utilities
0614 //---------------------------------------------------------------------------
0615 
0616 /// \brief Deduces and constructs a failure type from \p e
0617 ///
0618 /// \param e the failure value
0619 /// \return a constructed failure value
0620 template<typename E>
0621 RESULT_WARN_UNUSED constexpr auto
0622 fail(E&& e) noexcept(std::is_nothrow_constructible<typename std::decay<E>::type, E>::value)
0623     -> failure<typename std::decay<E>::type>;
0624 
0625 /// \brief Deduces a failure reference from a reverence_wrapper
0626 ///
0627 /// \param e the failure value
0628 /// \return a constructed failure reference
0629 template<typename E>
0630 RESULT_WARN_UNUSED constexpr auto fail(std::reference_wrapper<E> e) noexcept -> failure<E&>;
0631 
0632 /// \brief Constructs a failure type from a series of arguments
0633 ///
0634 /// \tparam E the failure type
0635 /// \param args the arguments to forward to E's constructor
0636 /// \return a constructed failure type
0637 template<typename E,
0638          typename... Args,
0639          typename = typename std::enable_if<std::is_constructible<E, Args...>::value>::type>
0640 RESULT_WARN_UNUSED constexpr auto fail(Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value)
0641     -> failure<E>;
0642 
0643 /// \brief Constructs a failure type from an initializer list and series of
0644 ///        arguments
0645 ///
0646 /// \tparam E the failure type
0647 /// \param args the arguments to forward to E's constructor
0648 /// \return a constructed failure type
0649 template<typename E,
0650          typename U,
0651          typename... Args,
0652          typename = typename std::enable_if<std::is_constructible<E, std::initializer_list<U>, Args...>::value>::type>
0653 RESULT_WARN_UNUSED constexpr auto
0654 fail(std::initializer_list<U> ilist,
0655      Args&&...args) noexcept(std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value) -> failure<E>;
0656 
0657 /// \brief Swaps the contents of two failure values
0658 ///
0659 /// \param lhs the left failure
0660 /// \param rhs the right failure
0661 template<typename E>
0662 auto swap(failure<E>& lhs, failure<E>& rhs)
0663 #if __cplusplus >= 201703L
0664     noexcept(std::is_nothrow_swappable<E>::value) -> void;
0665 #else
0666     noexcept(std::is_nothrow_move_constructible<E>::value) -> void;
0667 #endif
0668 
0669 namespace detail {
0670 
0671 //=========================================================================
0672 // class : unit
0673 //=========================================================================
0674 
0675 /// \brief A standalone monostate object (effectively std::monostate). This
0676 ///        exists to allow for `void` specializations
0677 struct unit {
0678 };
0679 
0680 //=========================================================================
0681 // non-member functions : class : unit
0682 //=========================================================================
0683 
0684 constexpr auto operator==(unit, unit) noexcept -> bool
0685 {
0686     return true;
0687 }
0688 constexpr auto operator!=(unit, unit) noexcept -> bool
0689 {
0690     return false;
0691 }
0692 constexpr auto operator<(unit, unit) noexcept -> bool
0693 {
0694     return false;
0695 }
0696 constexpr auto operator>(unit, unit) noexcept -> bool
0697 {
0698     return false;
0699 }
0700 constexpr auto operator<=(unit, unit) noexcept -> bool
0701 {
0702     return true;
0703 }
0704 constexpr auto operator>=(unit, unit) noexcept -> bool
0705 {
0706     return true;
0707 }
0708 
0709 //=========================================================================
0710 // class : detail::result_union<T, E, IsTrivial>
0711 //=========================================================================
0712 
0713 ///////////////////////////////////////////////////////////////////////////
0714 /// \brief A basic utility that acts as a union containing the T and E
0715 ///        types
0716 ///
0717 /// This is specialized on the case that both T and E are trivial, in which
0718 /// case `result_union` is also trivial
0719 ///
0720 /// \tparam T the value type result to be returned
0721 /// \tparam E the error type returned on failure
0722 /// \tparam IsTrivial Whether or not both T and E are trivial
0723 ///////////////////////////////////////////////////////////////////////////
0724 template<typename T,
0725          typename E,
0726          bool IsTrivial = std::is_trivially_destructible<T>::value&& std::is_trivially_destructible<E>::value>
0727 struct result_union {
0728     //-----------------------------------------------------------------------
0729     // Public Member Types
0730     //-----------------------------------------------------------------------
0731 
0732     using underlying_value_type = wrapped_result_type<T>;
0733     using underlying_error_type = E;
0734 
0735     //-----------------------------------------------------------------------
0736     // Constructors / Assignment
0737     //-----------------------------------------------------------------------
0738 
0739     /// \brief Constructs an empty object
0740     ///
0741     /// This is for use with conversion constructors, since it allows a
0742     /// temporary unused object to be set
0743     result_union(unit) noexcept;
0744 
0745     /// \brief Constructs the underlying value from the specified \p args
0746     ///
0747     /// \param args the arguments to forward to T's constructor
0748     template<typename... Args>
0749     constexpr result_union(in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value);
0750 
0751     /// \brief Constructs the underlying error from the specified \p args
0752     ///
0753     /// \param args the arguments to forward to E's constructor
0754     template<typename... Args>
0755     constexpr result_union(in_place_error_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value);
0756 
0757     result_union(const result_union&) = default;
0758     result_union(result_union&&) = default;
0759 
0760     //-----------------------------------------------------------------------
0761 
0762     auto operator=(const result_union&) -> result_union& = default;
0763     auto operator=(result_union&&) -> result_union& = default;
0764 
0765     //-----------------------------------------------------------------------
0766     // Modifiers
0767     //-----------------------------------------------------------------------
0768 
0769     /// \brief A no-op for trivial types
0770     auto destroy() const noexcept -> void;
0771 
0772     //-----------------------------------------------------------------------
0773     // Public Members
0774     //-----------------------------------------------------------------------
0775 
0776     union {
0777         underlying_value_type m_value;
0778         underlying_error_type m_error;
0779         unit m_empty;
0780     };
0781     bool m_has_value;
0782 };
0783 
0784 //-------------------------------------------------------------------------
0785 
0786 template<typename T, typename E>
0787 struct result_union<T, E, false> {
0788     //-----------------------------------------------------------------------
0789     // Public Member Types
0790     //-----------------------------------------------------------------------
0791 
0792     using underlying_value_type = wrapped_result_type<T>;
0793     using underlying_error_type = E;
0794 
0795     //-----------------------------------------------------------------------
0796     // Constructors / Assignment / Destructor
0797     //-----------------------------------------------------------------------
0798 
0799     /// \brief Constructs an empty object
0800     ///
0801     /// This is for use with conversion constructors, since it allows a
0802     /// temporary unused object to be set
0803     result_union(unit) noexcept;
0804 
0805     /// \brief Constructs the underlying value from the specified \p args
0806     ///
0807     /// \param args the arguments to forward to T's constructor
0808     template<typename... Args>
0809     constexpr result_union(in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value);
0810 
0811     /// \brief Constructs the underlying error from the specified \p args
0812     ///
0813     /// \param args the arguments to forward to E's constructor
0814     template<typename... Args>
0815     constexpr result_union(in_place_error_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value);
0816 
0817     result_union(const result_union&) = default;
0818     result_union(result_union&&) = default;
0819 
0820     //-----------------------------------------------------------------------
0821 
0822     /// \brief Destroys the underlying stored object
0823     ~result_union() noexcept(std::is_nothrow_destructible<T>::value&& std::is_nothrow_destructible<E>::value);
0824 
0825     //-----------------------------------------------------------------------
0826 
0827     auto operator=(const result_union&) -> result_union& = default;
0828     auto operator=(result_union&&) -> result_union& = default;
0829 
0830     //-----------------------------------------------------------------------
0831     // Modifiers
0832     //-----------------------------------------------------------------------
0833 
0834     /// \brief Destroys the underlying stored object
0835     auto destroy() -> void;
0836 
0837     //-----------------------------------------------------------------------
0838     // Public Members
0839     //-----------------------------------------------------------------------
0840 
0841     union {
0842         underlying_value_type m_value;
0843         underlying_error_type m_error;
0844         unit m_empty;
0845     };
0846     bool m_has_value;
0847 };
0848 
0849 //=========================================================================
0850 // class : result_construct_base<T, E>
0851 //=========================================================================
0852 
0853 ///////////////////////////////////////////////////////////////////////////
0854 /// \brief Base class of assignment to enable construction and assignment
0855 ///
0856 /// This class is used with several pieces of construction to ensure
0857 /// trivial constructibility and assignability:
0858 ///
0859 /// * `result_trivial_copy_ctor_base`
0860 /// * `result_trivial_move_ctor_base`
0861 /// * `result_copy_assign_base`
0862 /// * `result_move_assign_base`
0863 ///
0864 /// \tparam T the value type
0865 /// \tparam E the error type
0866 ///////////////////////////////////////////////////////////////////////////
0867 template<typename T, typename E>
0868 struct result_construct_base {
0869     //-----------------------------------------------------------------------
0870     // Constructors / Assignment
0871     //-----------------------------------------------------------------------
0872 
0873     /// \brief Constructs an empty object
0874     ///
0875     /// This is for use with conversion constructors, since it allows a
0876     /// temporary unused object to be set
0877     result_construct_base(unit) noexcept;
0878 
0879     /// \brief Constructs the underlying value from the specified \p args
0880     ///
0881     /// \param args the arguments to forward to T's constructor
0882     template<typename... Args>
0883     constexpr result_construct_base(in_place_t,
0884                                     Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value);
0885 
0886     /// \brief Constructs the underlying error from the specified \p args
0887     ///
0888     /// \param args the arguments to forward to E's constructor
0889     template<typename... Args>
0890     constexpr result_construct_base(in_place_error_t,
0891                                     Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value);
0892 
0893     result_construct_base(const result_construct_base&) = default;
0894     result_construct_base(result_construct_base&&) = default;
0895 
0896     auto operator=(const result_construct_base&) -> result_construct_base& = default;
0897     auto operator=(result_construct_base&&) -> result_construct_base& = default;
0898 
0899     //-----------------------------------------------------------------------
0900     // Construction / Assignment
0901     //-----------------------------------------------------------------------
0902 
0903     /// \brief Constructs the value type from \p args
0904     ///
0905     /// \note This is an implementation detail only meant to be used during
0906     ///       construction
0907     ///
0908     /// \pre there is no contained value or error at the time of construction
0909     ///
0910     /// \param args the arguments to forward to T's constructor
0911     template<typename... Args>
0912     auto construct_value(Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value) -> void;
0913 
0914     /// \brief Constructs the error type from \p args
0915     ///
0916     /// \note This is an implementation detail only meant to be used during
0917     ///       construction
0918     ///
0919     /// \pre there is no contained value or error at the time of construction
0920     ///
0921     /// \param args the arguments to forward to E's constructor
0922     template<typename... Args>
0923     auto construct_error(Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value) -> void;
0924 
0925     /// \brief Constructs the underlying error from the \p other result
0926     ///
0927     /// If \p other contains a value, then the T type will be
0928     /// default-constructed.
0929     ///
0930     /// \note This is an implementation detail only meant to be used during
0931     ///       construction of `result<void, E>` types
0932     ///
0933     /// \pre there is no contained value or error at the time of construction
0934     ///
0935     /// \param other the other result to construct
0936     template<typename Result>
0937     auto construct_error_from_result(Result&& other) -> void;
0938 
0939     /// \brief Constructs the underlying type from a result object
0940     ///
0941     /// \note This is an implementation detail only meant to be used during
0942     ///       construction
0943     ///
0944     /// \pre there is no contained value or error at the time of construction
0945     ///
0946     /// \param other the other result to construct
0947     template<typename Result>
0948     auto construct_from_result(Result&& other) -> void;
0949 
0950     //-----------------------------------------------------------------------
0951 
0952     template<typename Value>
0953     auto assign_value(Value&& value) noexcept(std::is_nothrow_assignable<T, Value>::value) -> void;
0954 
0955     template<typename Error>
0956     auto assign_error(Error&& error) noexcept(std::is_nothrow_assignable<E, Error>::value) -> void;
0957 
0958     template<typename Result>
0959     auto assign_from_result(Result&& other) -> void;
0960 
0961     //-----------------------------------------------------------------------
0962 
0963     template<typename ReferenceWrapper>
0964     auto construct_value_from_result_impl(std::true_type, ReferenceWrapper&& reference) noexcept -> void;
0965 
0966     template<typename Value>
0967     auto construct_value_from_result_impl(std::false_type,
0968                                           Value&& value) noexcept(std::is_nothrow_constructible<T, Value>::value)
0969         -> void;
0970 
0971     template<typename Result>
0972     auto assign_value_from_result_impl(std::true_type, Result&& other) -> void;
0973 
0974     template<typename Result>
0975     auto assign_value_from_result_impl(std::false_type, Result&& other) -> void;
0976 
0977     //-----------------------------------------------------------------------
0978     // Public Members
0979     //-----------------------------------------------------------------------
0980 
0981     using storage_type = result_union<T, E>;
0982 
0983     storage_type storage;
0984 };
0985 
0986 //=========================================================================
0987 // class : result_trivial_copy_ctor_base
0988 //=========================================================================
0989 
0990 template<typename T, typename E>
0991 struct result_trivial_copy_ctor_base_impl : result_construct_base<T, E> {
0992     using base_type = result_construct_base<T, E>;
0993     using base_type::base_type;
0994 
0995     result_trivial_copy_ctor_base_impl(const result_trivial_copy_ctor_base_impl& other) noexcept(
0996         std::is_nothrow_copy_constructible<T>::value&& std::is_nothrow_copy_constructible<E>::value);
0997     result_trivial_copy_ctor_base_impl(result_trivial_copy_ctor_base_impl&& other) = default;
0998 
0999     auto operator=(const result_trivial_copy_ctor_base_impl& other) -> result_trivial_copy_ctor_base_impl& = default;
1000     auto operator=(result_trivial_copy_ctor_base_impl&& other) -> result_trivial_copy_ctor_base_impl& = default;
1001 };
1002 
1003 template<bool Condition, typename Base>
1004 using conditionally_nest_type = typename std::conditional<Condition, typename Base::base_type, Base>::type;
1005 
1006 template<typename T, typename E>
1007 using result_trivial_copy_ctor_base = conditionally_nest_type<std::is_trivially_copy_constructible<T>::value
1008                                                                   && std::is_trivially_copy_constructible<E>::value,
1009                                                               result_trivial_copy_ctor_base_impl<T, E>>;
1010 
1011 //=========================================================================
1012 // class : result_trivial_move_ctor_base
1013 //=========================================================================
1014 
1015 template<typename T, typename E>
1016 struct result_trivial_move_ctor_base_impl : result_trivial_copy_ctor_base<T, E> {
1017     using base_type = result_trivial_copy_ctor_base<T, E>;
1018     using base_type::base_type;
1019 
1020     result_trivial_move_ctor_base_impl(const result_trivial_move_ctor_base_impl& other) = default;
1021     result_trivial_move_ctor_base_impl(result_trivial_move_ctor_base_impl&& other) noexcept(
1022         std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_constructible<E>::value);
1023 
1024     auto operator=(const result_trivial_move_ctor_base_impl& other) -> result_trivial_move_ctor_base_impl& = default;
1025     auto operator=(result_trivial_move_ctor_base_impl&& other) -> result_trivial_move_ctor_base_impl& = default;
1026 };
1027 
1028 template<typename T, typename E>
1029 using result_trivial_move_ctor_base = conditionally_nest_type<std::is_trivially_move_constructible<T>::value
1030                                                                   && std::is_trivially_move_constructible<E>::value,
1031                                                               result_trivial_move_ctor_base_impl<T, E>>;
1032 
1033 //=========================================================================
1034 // class : result_trivial_copy_assign_base
1035 //=========================================================================
1036 
1037 template<typename T, typename E>
1038 struct result_trivial_copy_assign_base_impl : result_trivial_move_ctor_base<T, E> {
1039     using base_type = result_trivial_move_ctor_base<T, E>;
1040     using base_type::base_type;
1041 
1042     result_trivial_copy_assign_base_impl(const result_trivial_copy_assign_base_impl& other) = default;
1043     result_trivial_copy_assign_base_impl(result_trivial_copy_assign_base_impl&& other) = default;
1044 
1045     auto operator=(const result_trivial_copy_assign_base_impl& other) noexcept(
1046         std::is_nothrow_copy_constructible<T>::value&& std::is_nothrow_copy_constructible<E>::value&&
1047             std::is_nothrow_copy_assignable<T>::value&& std::is_nothrow_copy_assignable<E>::value)
1048         -> result_trivial_copy_assign_base_impl&;
1049     auto operator=(result_trivial_copy_assign_base_impl&& other) -> result_trivial_copy_assign_base_impl& = default;
1050 };
1051 
1052 template<typename T, typename E>
1053 using result_trivial_copy_assign_base = conditionally_nest_type<
1054     std::is_trivially_copy_constructible<T>::value && std::is_trivially_copy_constructible<E>::value
1055         && std::is_trivially_copy_assignable<T>::value && std::is_trivially_copy_assignable<E>::value
1056         && std::is_trivially_destructible<T>::value && std::is_trivially_destructible<E>::value,
1057     result_trivial_copy_assign_base_impl<T, E>>;
1058 
1059 //=========================================================================
1060 // class : result_trivial_move_assign_base
1061 //=========================================================================
1062 
1063 template<typename T, typename E>
1064 struct result_trivial_move_assign_base_impl : result_trivial_copy_assign_base<T, E> {
1065     using base_type = result_trivial_copy_assign_base<T, E>;
1066     using base_type::base_type;
1067 
1068     result_trivial_move_assign_base_impl(const result_trivial_move_assign_base_impl& other) = default;
1069     result_trivial_move_assign_base_impl(result_trivial_move_assign_base_impl&& other) = default;
1070 
1071     auto operator=(const result_trivial_move_assign_base_impl& other)
1072         -> result_trivial_move_assign_base_impl& = default;
1073     auto operator=(result_trivial_move_assign_base_impl&& other) noexcept(
1074         std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_constructible<E>::value&&
1075             std::is_nothrow_move_assignable<T>::value&& std::is_nothrow_move_assignable<E>::value)
1076         -> result_trivial_move_assign_base_impl&;
1077 };
1078 
1079 template<typename T, typename E>
1080 using result_trivial_move_assign_base = conditionally_nest_type<
1081     std::is_trivially_move_constructible<T>::value && std::is_trivially_move_constructible<E>::value
1082         && std::is_trivially_move_assignable<T>::value && std::is_trivially_move_assignable<E>::value
1083         && std::is_trivially_destructible<T>::value && std::is_trivially_destructible<E>::value,
1084     result_trivial_move_assign_base_impl<T, E>>;
1085 
1086 //=========================================================================
1087 // class : disable_copy_ctor
1088 //=========================================================================
1089 
1090 template<typename T, typename E>
1091 struct disable_copy_ctor : result_trivial_move_assign_base<T, E> {
1092     using base_type = result_trivial_move_assign_base<T, E>;
1093     using base_type::base_type;
1094 
1095     disable_copy_ctor(const disable_copy_ctor& other) = delete;
1096     disable_copy_ctor(disable_copy_ctor&& other) = default;
1097 
1098     auto operator=(const disable_copy_ctor& other) -> disable_copy_ctor& = default;
1099     auto operator=(disable_copy_ctor&& other) -> disable_copy_ctor& = default;
1100 };
1101 
1102 template<typename T, typename E>
1103 using result_copy_ctor_base =
1104     conditionally_nest_type<std::is_copy_constructible<T>::value && std::is_copy_constructible<E>::value,
1105                             disable_copy_ctor<T, E>>;
1106 
1107 //=========================================================================
1108 // class : disable_move_ctor
1109 //=========================================================================
1110 
1111 template<typename T, typename E>
1112 struct disable_move_ctor : result_copy_ctor_base<T, E> {
1113     using base_type = result_copy_ctor_base<T, E>;
1114     using base_type::base_type;
1115 
1116     disable_move_ctor(const disable_move_ctor& other) = default;
1117     disable_move_ctor(disable_move_ctor&& other) = delete;
1118 
1119     auto operator=(const disable_move_ctor& other) -> disable_move_ctor& = default;
1120     auto operator=(disable_move_ctor&& other) -> disable_move_ctor& = default;
1121 };
1122 
1123 template<typename T, typename E>
1124 using result_move_ctor_base =
1125     conditionally_nest_type<std::is_move_constructible<T>::value && std::is_move_constructible<E>::value,
1126                             disable_move_ctor<T, E>>;
1127 
1128 //=========================================================================
1129 // class : disable_move_assignment
1130 //=========================================================================
1131 
1132 template<typename T, typename E>
1133 struct disable_move_assignment : result_move_ctor_base<T, E> {
1134     using base_type = result_move_ctor_base<T, E>;
1135     using base_type::base_type;
1136 
1137     disable_move_assignment(const disable_move_assignment& other) = default;
1138     disable_move_assignment(disable_move_assignment&& other) = default;
1139 
1140     auto operator=(const disable_move_assignment& other) -> disable_move_assignment& = delete;
1141     auto operator=(disable_move_assignment&& other) -> disable_move_assignment& = default;
1142 };
1143 
1144 template<typename T, typename E>
1145 using result_copy_assign_base =
1146     conditionally_nest_type<std::is_nothrow_copy_constructible<T>::value && std::is_nothrow_copy_constructible<E>::value
1147                                 && std::is_copy_assignable<wrapped_result_type<T>>::value
1148                                 && std::is_copy_assignable<E>::value,
1149                             disable_move_assignment<T, E>>;
1150 
1151 //=========================================================================
1152 // class : disable_copy_assignment
1153 //=========================================================================
1154 
1155 template<typename T, typename E>
1156 struct disable_copy_assignment : result_copy_assign_base<T, E> {
1157     using base_type = result_copy_assign_base<T, E>;
1158     using base_type::base_type;
1159 
1160     disable_copy_assignment(const disable_copy_assignment& other) = default;
1161     disable_copy_assignment(disable_copy_assignment&& other) = default;
1162 
1163     auto operator=(const disable_copy_assignment& other) -> disable_copy_assignment& = default;
1164     auto operator=(disable_copy_assignment&& other) -> disable_copy_assignment& = delete;
1165 };
1166 
1167 template<typename T, typename E>
1168 using result_move_assign_base =
1169     conditionally_nest_type<std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_constructible<E>::value
1170                                 && std::is_move_assignable<wrapped_result_type<T>>::value
1171                                 && std::is_move_assignable<E>::value,
1172                             disable_copy_assignment<T, E>>;
1173 
1174 //=========================================================================
1175 // alias : result_storage
1176 //=========================================================================
1177 
1178 template<typename T, typename E>
1179 using result_storage = result_move_assign_base<T, E>;
1180 
1181 //=========================================================================
1182 // traits : result
1183 //=========================================================================
1184 
1185 template<typename T1, typename E1, typename T2, typename E2>
1186 using result_is_convertible = std::integral_constant<
1187     bool,
1188     (
1189         // T1 constructible from result<T2,E2>
1190         std::is_constructible<T1, result<T2, E2>&>::value || std::is_constructible<T1, const result<T2, E2>&>::value
1191         || std::is_constructible<T1, result<T2, E2>&&>::value
1192         || std::is_constructible<T1, const result<T2, E2>&&>::value ||
1193 
1194         // E1 constructible from result<T2,E2>
1195         std::is_constructible<E1, result<T2, E2>&>::value || std::is_constructible<E1, const result<T2, E2>&>::value
1196         || std::is_constructible<E1, result<T2, E2>&&>::value
1197         || std::is_constructible<E1, const result<T2, E2>&&>::value ||
1198 
1199         // result<T2,E2> convertible to T1
1200         std::is_convertible<result<T2, E2>&, T1>::value || std::is_convertible<const result<T2, E2>&, T1>::value
1201         || std::is_convertible<result<T2, E2>&&, T1>::value || std::is_convertible<const result<T2, E2>&&, T1>::value ||
1202 
1203         // result<T2,E2> convertible to E2
1204         std::is_convertible<result<T2, E2>&, E1>::value || std::is_convertible<const result<T2, E2>&, E1>::value
1205         || std::is_convertible<result<T2, E2>&&, E1>::value || std::is_convertible<const result<T2, E2>&&, E1>::value)>;
1206 
1207 //-------------------------------------------------------------------------
1208 
1209 template<typename T1, typename E1, typename T2, typename E2>
1210 using result_is_copy_convertible =
1211     std::integral_constant<bool,
1212                            (!result_is_convertible<T1, E1, T2, E2>::value && std::is_constructible<T1, const T2&>::value
1213                             && std::is_constructible<E1, const E2&>::value)>;
1214 
1215 template<typename T1, typename E1, typename T2, typename E2>
1216 using result_is_implicit_copy_convertible =
1217     std::integral_constant<bool,
1218                            (result_is_copy_convertible<T1, E1, T2, E2>::value
1219                             && std::is_convertible<const T2&, T1>::value && std::is_convertible<const E2&, E1>::value)>;
1220 
1221 template<typename T1, typename E1, typename T2, typename E2>
1222 using result_is_explicit_copy_convertible =
1223     std::integral_constant<bool,
1224                            (result_is_copy_convertible<T1, E1, T2, E2>::value
1225                             && (!std::is_convertible<const T2&, T1>::value
1226                                 || !std::is_convertible<const E2&, E1>::value))>;
1227 
1228 //-------------------------------------------------------------------------
1229 
1230 template<typename T1, typename E1, typename T2, typename E2>
1231 using result_is_move_convertible =
1232     std::integral_constant<bool,
1233                            (!result_is_convertible<T1, E1, T2, E2>::value && std::is_constructible<T1, T2&&>::value
1234                             && std::is_constructible<E1, E2&&>::value)>;
1235 
1236 template<typename T1, typename E1, typename T2, typename E2>
1237 using result_is_implicit_move_convertible =
1238     std::integral_constant<bool,
1239                            (result_is_move_convertible<T1, E1, T2, E2>::value && std::is_convertible<T2&&, T1>::value
1240                             && std::is_convertible<E2&&, E1>::value)>;
1241 
1242 template<typename T1, typename E1, typename T2, typename E2>
1243 using result_is_explicit_move_convertible =
1244     std::integral_constant<bool,
1245                            (result_is_move_convertible<T1, E1, T2, E2>::value
1246                             && (!std::is_convertible<T2&&, T1>::value || !std::is_convertible<E2&&, E1>::value))>;
1247 
1248 //-------------------------------------------------------------------------
1249 
1250 template<typename T, typename U>
1251 using result_is_value_convertible =
1252     std::integral_constant<bool,
1253                            (std::is_constructible<T, U&&>::value
1254                             && !std::is_same<typename std::decay<U>::type, in_place_t>::value
1255                             && !std::is_same<typename std::decay<U>::type, in_place_error_t>::value
1256                             && !is_result<typename std::decay<U>::type>::value)>;
1257 
1258 template<typename T, typename U>
1259 using result_is_explicit_value_convertible =
1260     std::integral_constant<bool, (result_is_value_convertible<T, U>::value && !std::is_convertible<U&&, T>::value)>;
1261 
1262 template<typename T, typename U>
1263 using result_is_implicit_value_convertible =
1264     std::integral_constant<bool, (result_is_value_convertible<T, U>::value && std::is_convertible<U&&, T>::value)>;
1265 
1266 //-------------------------------------------------------------------------
1267 
1268 template<typename T1, typename E1, typename T2, typename E2>
1269 using result_is_convert_assignable = std::integral_constant<
1270     bool,
1271     (result_is_convertible<T1, E1, T2, E2>::value &&
1272 
1273      std::is_assignable<T1&, result<T2, E2>&>::value && std::is_assignable<T1&, const result<T2, E2>&>::value
1274      && std::is_assignable<T1&, result<T2, E2>&&>::value && std::is_assignable<T1&, const result<T2, E2>&&>::value &&
1275 
1276      std::is_assignable<E1&, result<T2, E2>&>::value && std::is_assignable<E1&, const result<T2, E2>&>::value
1277      && std::is_assignable<E1&, result<T2, E2>&&>::value && std::is_assignable<E1&, const result<T2, E2>&&>::value)>;
1278 
1279 template<typename T1, typename E1, typename T2, typename E2>
1280 using result_is_copy_convert_assignable =
1281     std::integral_constant<bool,
1282                            (!result_is_convert_assignable<T1, E1, T2, E2>::value &&
1283 
1284                             std::is_nothrow_constructible<T1, const T2&>::value
1285                             && std::is_assignable<wrapped_result_type<T1>&, const T2&>::value
1286                             && std::is_nothrow_constructible<E1, const E2&>::value
1287                             && std::is_assignable<E1&, const E2&>::value)>;
1288 
1289 template<typename T1, typename E1, typename T2, typename E2>
1290 using result_is_move_convert_assignable =
1291     std::integral_constant<bool,
1292                            (!result_is_convert_assignable<T1, E1, T2, E2>::value &&
1293 
1294                             std::is_nothrow_constructible<T1, T2&&>::value && std::is_assignable<T1&, T2&&>::value
1295                             && std::is_nothrow_constructible<E1, E2&&>::value && std::is_assignable<E1&, E2&&>::value)>;
1296 
1297 //-------------------------------------------------------------------------
1298 
1299 template<typename T, typename U>
1300 using result_is_value_assignable = std::integral_constant<
1301     bool,
1302     (!is_result<typename std::decay<U>::type>::value && !is_failure<typename std::decay<U>::type>::value
1303      && std::is_nothrow_constructible<T, U>::value && std::is_assignable<wrapped_result_type<T>&, U>::value
1304      && (!std::is_same<typename std::decay<U>::type, typename std::decay<T>::type>::value
1305          || !std::is_scalar<T>::value))>;
1306 
1307 template<typename E, typename E2>
1308 using result_is_failure_assignable =
1309     std::integral_constant<bool, (std::is_nothrow_constructible<E, E2>::value && std::is_assignable<E&, E2>::value)>;
1310 
1311 // Friending 'extract_error" below was causing some compilers to incorrectly
1312 // identify `exp.m_storage.m_error` as being an access violation despite the
1313 // friendship. Using a type name instead seems to be ubiquitous across
1314 // compilers
1315 struct result_error_extractor {
1316     template<typename T, typename E>
1317     static constexpr auto get(const result<T, E>& exp) noexcept -> const E&;
1318     template<typename T, typename E>
1319     static constexpr auto get(result<T, E>& exp) noexcept -> E&;
1320 };
1321 
1322 template<typename T, typename E>
1323 constexpr auto extract_error(const result<T, E>& exp) noexcept -> const E&;
1324 
1325 template<typename E>
1326 [[noreturn]] auto throw_bad_result_access(E&& error) -> void;
1327 
1328 template<typename String, typename E>
1329 [[noreturn]] auto throw_bad_result_access_message(String&& message, E&& error) -> void;
1330 
1331 } // namespace detail
1332 
1333 /////////////////////////////////////////////////////////////////////////////
1334 /// \brief The class template `result` manages result results from APIs,
1335 ///        while encoding possible failure conditions.
1336 ///
1337 /// A common use-case for result is the return value of a function that
1338 /// may fail. As opposed to other approaches, such as `std::pair<T,bool>`
1339 /// or `std::optional`, `result` more accurately conveys the intent of the
1340 /// user along with the failure condition to the caller. This effectively
1341 /// produces an orthogonal error handling mechanism that allows for exception
1342 /// safety while also allowing discrete testability of the return type.
1343 ///
1344 /// `result<T,E>` types may contain a `T` value, which signifies that an
1345 /// operation succeeded in producing the result value of type `T`. If an
1346 /// `result` does not contain a `T` value, it will always contain an `E`
1347 /// error condition instead.
1348 ///
1349 /// An `result<T,E>` can always be queried for a possible error case by
1350 /// calling the `error()` function, even if it contains a value.
1351 /// In the case that a `result<T,E>` contains a value object, this will
1352 /// simply return an `E` object constructed through default aggregate
1353 /// construction, as if through the expression `E{}`, which is assumed to be
1354 /// a "valid" (no-error) state for an `E` type.
1355 /// For example:
1356 ///
1357 /// * `std::error_code{}` produces a default-construct error-code, which is
1358 ///   the "no error" state,
1359 /// * integral (or enum) error codes produce a `0` value (no error), thanks to
1360 ///   zero-initialization,
1361 /// * `std::exception_ptr{}` produces a null-pointer,
1362 /// * `std::string{}` produces an empty string `""`,
1363 /// * etc.
1364 ///
1365 /// When a `result<T,E>` contains either a value or error, the storage for
1366 /// that object is guaranteed to be allocated as part of the result
1367 /// object's footprint, i.e. no dynamic memory allocation ever takes place.
1368 /// Thus, a result object models an object, not a pointer, even though the
1369 /// `operator*()` and `operator->()` are defined.
1370 ///
1371 /// When an object of type `result<T,E>` is contextually converted to
1372 /// `bool`, the conversion returns `true` if the object contains a value and
1373 /// `false` if it contains an error.
1374 ///
1375 /// `result` objects do not have a "valueless" state like `variant`s do.
1376 /// Once a `result` has been constructed with a value or error, the
1377 /// active underlying type can only be changed through assignment which may
1378 /// is only enabled if construction is guaranteed to be *non-throwing*. This
1379 /// ensures that a valueless state cannot occur naturally.
1380 ///
1381 /// Example Use:
1382 /// \code
1383 /// auto to_string(int x) -> result<std::string>
1384 /// {
1385 ///   try {
1386 ///     return std::stoi(x);
1387 ///   } catch (const std::invalid_argument&) {
1388 ///     return fail(std::errc::invalid_argument);
1389 ///   } catch (const std::std::out_of_range&) {
1390 ///     return fail(std::errc::result_out_of_range);
1391 ///   }
1392 /// }
1393 /// \endcode
1394 ///
1395 /// \note If using C++17 or above, `fail` can be replaced with
1396 ///       `failure{...}` thanks to CTAD.
1397 ///
1398 /// \tparam T the underlying value type
1399 /// \tparam E the underlying error type
1400 ///////////////////////////////////////////////////////////////////////////
1401 template<typename T, typename E>
1402 class RESULT_NODISCARD result {
1403     // Type requirements
1404 
1405     static_assert(!std::is_abstract<T>::value, "It is ill-formed for T to be abstract type");
1406     static_assert(!std::is_same<typename std::decay<T>::type, in_place_t>::value,
1407                   "It is ill-formed for T to be a (possibly CV-qualified) in_place_t type");
1408     static_assert(!is_result<typename std::decay<T>::type>::value,
1409                   "It is ill-formed for T to be a (possibly CV-qualified) 'result' type");
1410     static_assert(!is_failure<typename std::decay<T>::type>::value,
1411                   "It is ill-formed for T to be a (possibly CV-qualified) 'failure' type");
1412     static_assert(!std::is_rvalue_reference<T>::value,
1413                   "It is ill-formed for T to be an rvalue 'result type. "
1414                   "Only lvalue references are valid.");
1415 
1416     static_assert(!std::is_abstract<E>::value, "It is ill-formed for E to be abstract type");
1417     static_assert(!std::is_void<typename std::decay<E>::type>::value,
1418                   "It is ill-formed for E to be (possibly CV-qualified) void type");
1419     static_assert(!is_result<typename std::decay<E>::type>::value,
1420                   "It is ill-formed for E to be a (possibly CV-qualified) 'result' type");
1421     static_assert(!is_failure<typename std::decay<E>::type>::value,
1422                   "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type");
1423     static_assert(!std::is_same<typename std::decay<E>::type, in_place_t>::value,
1424                   "It is ill-formed for E to be a (possibly CV-qualified) in_place_t type");
1425     static_assert(!std::is_reference<E>::value,
1426                   "It is ill-formed for E to be a reference type. "
1427                   "Only T types may be lvalue references");
1428 
1429     // Friendship
1430 
1431     friend detail::result_error_extractor;
1432 
1433     template<typename T2, typename E2>
1434     friend class result;
1435 
1436     //-------------------------------------------------------------------------
1437     // Public Member Types
1438     //-------------------------------------------------------------------------
1439   public:
1440     using value_type = T; ///< The value type of this result
1441     using error_type = E; ///< The error type of this result
1442     using failure_type = failure<E>; ///< The failure type
1443 
1444     template<typename U>
1445     using rebind = result<U, E>; ///< Rebinds the result type
1446 
1447     //-------------------------------------------------------------------------
1448     // Constructor / Destructor / Assignment
1449     //-------------------------------------------------------------------------
1450   public:
1451     /// \brief Default-constructs a result with the underlying value type
1452     ///        active
1453     ///
1454     /// This constructor is only enabled if `T` is default-constructible
1455     ///
1456     /// ### Examples
1457     ///
1458     /// Basic Usage:
1459     ///
1460     /// ```cpp
1461     /// assert(cpp::result<std::string,int>{} == std::string{});
1462     /// ```
1463     template<typename U = T, typename = typename std::enable_if<std::is_constructible<U>::value>::type>
1464     constexpr result() noexcept(std::is_nothrow_constructible<U>::value);
1465 
1466     /// \brief Copy constructs this result
1467     ///
1468     /// If \p other contains a value, initializes the contained value as if
1469     /// direct-initializing (but not direct-list-initializing) an object of
1470     /// type `T` with the expression *other.
1471     ///
1472     /// If other contains an error, constructs an object that contains a copy
1473     /// of that error.
1474     ///
1475     /// \note This constructor is defined as deleted if
1476     ///       `std::is_copy_constructible<T>::value` or
1477     ///       `std::is_copy_constructible<E>::value` is `false`
1478     ///
1479     /// \note This constructor is defined as trivial if both
1480     ///       `std::is_trivially_copy_constructible<T>::value` and
1481     ///       `std::is_trivially_copy_constructible<E>::value` are `true`
1482     ///
1483     /// ### Examples
1484     ///
1485     /// Basic Usage:
1486     ///
1487     /// ```cpp
1488     /// const auto r = cpp::result<int,int>{42};
1489     /// const auto s = r;
1490     ///
1491     /// assert(r == s);
1492     /// ```
1493     ///
1494     /// \param other the result to copy
1495     constexpr result(const result& other) = default;
1496 
1497     /// \brief Move constructs a result
1498     ///
1499     /// If other contains a value, initializes the contained value as if
1500     /// direct-initializing (but not direct-list-initializing) an object
1501     /// of type T with the expression `std::move(*other)` and does not make
1502     /// other empty: a moved-from result still contains a value, but the
1503     /// value itself is moved from.
1504     ///
1505     /// If other contains an error, move-constructs this result from that
1506     /// error.
1507     ///
1508     /// \note This constructor is defined as deleted if
1509     ///       `std::is_move_constructible<T>::value` or
1510     ///       `std::is_move_constructible<E>::value` is `false`
1511     ///
1512     /// \note This constructor is defined as trivial if both
1513     ///       `std::is_trivially_move_constructible<T>::value` and
1514     ///       `std::is_trivially_move_constructible<E>::value` are `true`
1515     ///
1516     /// ### Examples
1517     ///
1518     /// Basic Usage:
1519     ///
1520     /// ```cpp
1521     /// auto r = cpp::result<std::string,int>{"hello world"};
1522     /// auto s = std::move(r);
1523     ///
1524     /// assert(s == "hello world");
1525     /// ```
1526     ///
1527     /// \param other the result to move
1528     constexpr result(result&& other) = default;
1529 
1530     /// \{
1531     /// \brief Converting copy constructor
1532     ///
1533     /// If \p other contains a value, constructs a result object
1534     /// that contains a value, initialized as if direct-initializing
1535     /// (but not direct-list-initializing) an object of type `T` with the
1536     /// expression `*other`.
1537     ///
1538     /// If \p other contains an error, constructs a result object that
1539     /// contains an error, initialized as if direct-initializing
1540     /// (but not direct-list-initializing) an object of type `E`.
1541     ///
1542     /// \note This constructor does not participate in overload resolution
1543     ///       unless the following conditions are met:
1544     ///       - `std::is_constructible_v<T, const U&>` is `true`
1545     ///       - T is not constructible or convertible from any expression
1546     ///         of type (possibly const) `result<T2,E2>`
1547     ///       - E is not constructible or convertible from any expression
1548     ///         of type (possible const) `result<T2,E2>`
1549     ///
1550     /// \note This constructor is explicit if and only if
1551     ///       `std::is_convertible_v<const T2&, T>` or
1552     ///       `std::is_convertible_v<const E2&, E>` is `false`
1553     ///
1554     /// ### Examples
1555     ///
1556     /// Basic Usage:
1557     ///
1558     /// ```cpp
1559     /// const auto r = cpp::result<int,int>{42};
1560     /// const auto s = cpp::result<long,long>{r};
1561     ///
1562     /// assert(r == s);
1563     /// ```
1564     ///
1565     /// \param other the other type to convert
1566     template<typename T2,
1567              typename E2,
1568              typename std::enable_if<detail::result_is_implicit_copy_convertible<T, E, T2, E2>::value, int>::type = 0>
1569     result(const result<T2, E2>& other) noexcept(
1570         std::is_nothrow_constructible<T, const T2&>::value&& std::is_nothrow_constructible<E, const E2&>::value);
1571     template<typename T2,
1572              typename E2,
1573              typename std::enable_if<detail::result_is_explicit_copy_convertible<T, E, T2, E2>::value, int>::type = 0>
1574     explicit result(const result<T2, E2>& other) noexcept(
1575         std::is_nothrow_constructible<T, const T2&>::value&& std::is_nothrow_constructible<E, const E2&>::value);
1576     /// \}
1577 
1578     /// \{
1579     /// \brief Converting move constructor
1580     ///
1581     /// If \p other contains a value, constructs a result object
1582     /// that contains a value, initialized as if direct-initializing
1583     /// (but not direct-list-initializing) an object of type T with the
1584     /// expression `std::move(*other)`.
1585     ///
1586     /// If \p other contains an error, constructs a result object that
1587     /// contains an error, initialized as if direct-initializing
1588     /// (but not direct-list-initializing) an object of type E&&.
1589     ///
1590     /// \note This constructor does not participate in overload resolution
1591     ///       unless the following conditions are met:
1592     ///       - `std::is_constructible_v<T, const U&>` is `true`
1593     ///       - T is not constructible or convertible from any expression
1594     ///         of type (possibly const) `result<T2,E2>`
1595     ///       - E is not constructible or convertible from any expression
1596     ///         of type (possible const) `result<T2,E2>`
1597     ///
1598     /// \note This constructor is explicit if and only if
1599     ///       `std::is_convertible_v<const T2&, T>` or
1600     ///       `std::is_convertible_v<const E2&, E>` is `false`
1601     ///
1602     /// ### Examples
1603     ///
1604     /// Basic Usage:
1605     ///
1606     /// ```cpp
1607     /// auto r = cpp::result<std::unique_ptr<Derived>,int>{
1608     ///   std::make_unique<Derived>()
1609     /// };
1610     /// const auto s = cpp::result<std::unique_ptr<Base>,long>{
1611     ///   std::move(r)
1612     /// };
1613     /// ```
1614     ///
1615     /// \param other the other type to convert
1616     template<typename T2,
1617              typename E2,
1618              typename std::enable_if<detail::result_is_implicit_move_convertible<T, E, T2, E2>::value, int>::type = 0>
1619     result(result<T2, E2>&& other) noexcept(
1620         std::is_nothrow_constructible<T, T2&&>::value&& std::is_nothrow_constructible<E, E2&&>::value);
1621     template<typename T2,
1622              typename E2,
1623              typename std::enable_if<detail::result_is_explicit_move_convertible<T, E, T2, E2>::value, int>::type = 0>
1624     explicit result(result<T2, E2>&& other) noexcept(
1625         std::is_nothrow_constructible<T, T2&&>::value&& std::is_nothrow_constructible<E, E2&&>::value);
1626     /// \}
1627 
1628     //-------------------------------------------------------------------------
1629 
1630     /// \brief Constructs a result object that contains a value
1631     ///
1632     /// The value is initialized as if direct-initializing (but not
1633     /// direct-list-initializing) an object of type `T` from the arguments
1634     /// `std::forward<Args>(args)...`
1635     ///
1636     /// ### Examples
1637     ///
1638     /// Basic Usage:
1639     ///
1640     /// ```cpp
1641     /// auto r = cpp::result<std::string,int>{
1642     ///   cpp::in_place, "Hello world"
1643     /// };
1644     /// ```
1645     ///
1646     /// \param args the arguments to pass to T's constructor
1647     template<typename... Args, typename = typename std::enable_if<std::is_constructible<T, Args...>::value>::type>
1648     constexpr explicit result(in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value);
1649 
1650     /// \brief Constructs a result object that contains a value
1651     ///
1652     /// The value is initialized as if direct-initializing (but not
1653     /// direct-list-initializing) an object of type `T` from the arguments
1654     /// `std::forward<std::initializer_list<U>>(ilist)`,
1655     /// `std::forward<Args>(args)...`
1656     ///
1657     /// ### Examples
1658     ///
1659     /// Basic Usage:
1660     ///
1661     /// ```cpp
1662     /// auto r = cpp::result<std::string,int>{
1663     ///   cpp::in_place, {'H','e','l','l','o'}
1664     /// };
1665     /// ```
1666     ///
1667     /// \param ilist An initializer list of entries to forward
1668     /// \param args  the arguments to pass to T's constructor
1669     template<
1670         typename U,
1671         typename... Args,
1672         typename = typename std::enable_if<std::is_constructible<T, std::initializer_list<U>&, Args...>::value>::type>
1673     constexpr explicit result(in_place_t, std::initializer_list<U> ilist, Args&&...args) noexcept(
1674         std::is_nothrow_constructible<T, std::initializer_list<U>, Args...>::value);
1675 
1676     //-------------------------------------------------------------------------
1677 
1678     /// \brief Constructs a result object that contains an error
1679     ///
1680     /// the value is initialized as if direct-initializing (but not
1681     /// direct-list-initializing) an object of type `E` from the arguments
1682     /// `std::forward<Args>(args)...`
1683     ///
1684     /// ### Examples
1685     ///
1686     /// Basic Usage:
1687     ///
1688     /// ```cpp
1689     /// auto r = cpp::result<int,std::string>{
1690     ///   cpp::in_place_error, "Hello world"
1691     /// };
1692     /// ```
1693     ///
1694     /// \param args the arguments to pass to E's constructor
1695     template<typename... Args, typename = typename std::enable_if<std::is_constructible<E, Args...>::value>::type>
1696     constexpr explicit result(in_place_error_t,
1697                               Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value);
1698 
1699     /// \brief Constructs a result object that contains an error
1700     ///
1701     /// The value is initialized as if direct-initializing (but not
1702     /// direct-list-initializing) an object of type `E` from the arguments
1703     /// `std::forward<std::initializer_list<U>>(ilist)`,
1704     /// `std::forward<Args>(args)...`
1705     ///
1706     /// ### Examples
1707     ///
1708     /// Basic Usage:
1709     ///
1710     /// ```cpp
1711     /// auto r = cpp::result<int,std::string>{
1712     ///   cpp::in_place_error, {'H','e','l','l','o'}
1713     /// };
1714     /// ```
1715     ///
1716     /// \param ilist An initializer list of entries to forward
1717     /// \param args  the arguments to pass to Es constructor
1718     template<
1719         typename U,
1720         typename... Args,
1721         typename = typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
1722     constexpr explicit result(in_place_error_t, std::initializer_list<U> ilist, Args&&...args) noexcept(
1723         std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value);
1724 
1725     //-------------------------------------------------------------------------
1726 
1727     /// \{
1728     /// \brief Constructs the underlying error of this result
1729     ///
1730     /// \note This constructor only participates in overload resolution if
1731     ///       `E` is constructible from \p e
1732     ///
1733     /// ### Examples
1734     ///
1735     /// Basic Usage:
1736     ///
1737     /// ```cpp
1738     /// cpp::result<int,int> r = cpp::fail(42);
1739     ///
1740     /// auto get_error_result() -> cpp::result<int,std::string> {
1741     ///   return cpp::fail("hello world!");
1742     /// }
1743     /// ```
1744     ///
1745     /// \param e the failure error
1746     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, const E2&>::value>::type>
1747     constexpr /* implicit */ result(const failure<E2>& e) noexcept(std::is_nothrow_constructible<E, const E2&>::value);
1748     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, E2&&>::value>::type>
1749     constexpr /* implicit */ result(failure<E2>&& e) noexcept(std::is_nothrow_constructible<E, E2&&>::value);
1750     /// \}
1751 
1752     /// \{
1753     /// \brief Constructs a result object that contains a value
1754     ///
1755     /// The value is initialized as if direct-initializing (but not
1756     /// direct-list-initializing) an object of type T with the expression
1757     /// value.
1758     ///
1759     /// \note This constructor is constexpr if the constructor of T
1760     ///       selected by direct-initialization is constexpr
1761     ///
1762     /// \note This constructor does not participate in overload
1763     ///       resolution unless `std::is_constructible_v<T, U&&>` is true
1764     ///       and `decay_t<U>` is neither `in_place_t`, `in_place_error_t`,
1765     ///       nor a `result` type.
1766     ///
1767     /// \note This constructor is explicit if and only if
1768     ///       `std::is_convertible_v<U&&, T>` is `false`
1769     ///
1770     /// ### Examples
1771     ///
1772     /// Basic Usage:
1773     ///
1774     /// ```cpp
1775     /// cpp::result<int,int> r = 42;
1776     ///
1777     /// auto get_value() -> cpp::result<std::string,int> {
1778     ///   return "hello world!"; // implicit conversion
1779     /// }
1780     /// ```
1781     ///
1782     /// \param value the value to copy
1783     template<typename U,
1784              typename std::enable_if<detail::result_is_explicit_value_convertible<T, U>::value, int>::type = 0>
1785     constexpr explicit result(U&& value) noexcept(std::is_nothrow_constructible<T, U>::value);
1786     template<typename U,
1787              typename std::enable_if<detail::result_is_implicit_value_convertible<T, U>::value, int>::type = 0>
1788     constexpr /* implicit */ result(U&& value) noexcept(std::is_nothrow_constructible<T, U>::value);
1789     /// \}
1790 
1791     //-------------------------------------------------------------------------
1792 
1793     /// \brief Copy assigns the result stored in \p other
1794     ///
1795     /// \note This assignment operator only participates in overload resolution
1796     ///       if the following conditions are met:
1797     ///       - `std::is_nothrow_copy_constructible_v<T>` is `true`, and
1798     ///       - `std::is_nothrow_copy_constructible_v<E>` is `true`
1799     ///       this restriction guarantees that no '
1800     ///
1801     /// \note This assignment operator is defined as trivial if the following
1802     ///       conditions are all `true`:
1803     ///       - `std::is_trivially_copy_constructible<T>::value`
1804     ///       - `std::is_trivially_copy_constructible<E>::value`
1805     ///       - `std::is_trivially_copy_assignable<T>::value`
1806     ///       - `std::is_trivially_copy_assignable<E>::value`
1807     ///       - `std::is_trivially_destructible<T>::value`
1808     ///       - `std::is_trivially_destructible<E>::value`
1809     ///
1810     /// \param other the other result to copy
1811     auto operator=(const result& other) -> result& = default;
1812 
1813     /// \brief Move assigns the result stored in \p other
1814     ///
1815     /// \note This assignment operator only participates in overload resolution
1816     ///       if the following conditions are met:
1817     ///       - `std::is_nothrow_copy_constructible_v<T>` is `true`, and
1818     ///       - `std::is_nothrow_copy_constructible_v<E>` is `true`
1819     ///       this restriction guarantees that no 'valueless_by_exception` state
1820     ///       may occur.
1821     ///
1822     /// \note This assignment operator is defined as trivial if the following
1823     ///       conditions are all `true`:
1824     ///       - `std::is_trivially_move_constructible<T>::value`
1825     ///       - `std::is_trivially_move_constructible<E>::value`
1826     ///       - `std::is_trivially_move_assignable<T>::value`
1827     ///       - `std::is_trivially_move_assignable<E>::value`
1828     ///       - `std::is_trivially_destructible<T>::value`
1829     ///       - `std::is_trivially_destructible<E>::value`
1830     ///
1831     /// \param other the other result to copy
1832     auto operator=(result&& other) -> result& = default;
1833 
1834     /// \brief Copy-converts the state of \p other
1835     ///
1836     /// If both `*this` and \p other contain either values or errors, the
1837     /// underlying value is constructed as if through assignment.
1838     ///
1839     /// Otherwise if `*this` contains a value, but \p other contains an error,
1840     /// then the contained value is destroyed by calling its destructor. `*this`
1841     /// will no longer contain a value after the call, and will now contain `E`
1842     /// constructed as if direct-initializing (but not direct-list-initializing)
1843     /// an object with an argument of `const E2&`.
1844     ///
1845     /// If \p other contains a value and `*this` contains an error, then the
1846     /// contained error is destroyed by calling its destructor. `*this` now
1847     /// contains a value constructed as if direct-initializing (but not
1848     /// direct-list-initializing) an object with an argument of `const T2&`.
1849     ///
1850     /// \note The function does not participate in overload resolution unless
1851     ///       - `std::is_nothrow_constructible_v<T, const T2&>`,
1852     ///         `std::is_assignable_v<T&, const T2&>`,
1853     ///         `std::is_nothrow_constructible_v<E, const E2&>`,
1854     ///         `std::is_assignable_v<E&, const E2&>` are all true.
1855     ///       - T is not constructible, convertible, or assignable from any
1856     ///         expression of type (possibly const) `result<T2,E2>`
1857     ///
1858     /// \param other the other result object to convert
1859     /// \return reference to `(*this)`
1860     template<typename T2,
1861              typename E2,
1862              typename = typename std::enable_if<detail::result_is_copy_convert_assignable<T, E, T2, E2>::value>::type>
1863     auto operator=(const result<T2, E2>& other) noexcept(
1864         std::is_nothrow_assignable<T, const T2&>::value&& std::is_nothrow_assignable<E, const E2&>::value) -> result&;
1865 
1866     /// \brief Move-converts the state of \p other
1867     ///
1868     /// If both `*this` and \p other contain either values or errors, the
1869     /// underlying value is constructed as if through move-assignment.
1870     ///
1871     /// Otherwise if `*this` contains a value, but \p other contains an error,
1872     /// then the contained value is destroyed by calling its destructor. `*this`
1873     /// will no longer contain a value after the call, and will now contain `E`
1874     /// constructed as if direct-initializing (but not direct-list-initializing)
1875     /// an object with an argument of `E2&&`.
1876     ///
1877     /// If \p other contains a value and `*this` contains an error, then the
1878     /// contained error is destroyed by calling its destructor. `*this` now
1879     /// contains a value constructed as if direct-initializing (but not
1880     /// direct-list-initializing) an object with an argument of `T2&&`.
1881     ///
1882     /// \note The function does not participate in overload resolution unless
1883     ///       - `std::is_nothrow_constructible_v<T, T2&&>`,
1884     ///         `std::is_assignable_v<T&, T2&&>`,
1885     ///         `std::is_nothrow_constructible_v<E, E2&&>`,
1886     ///         `std::is_assignable_v<E&, E2&&>` are all true.
1887     ///       - T is not constructible, convertible, or assignable from any
1888     ///         expression of type (possibly const) `result<T2,E2>`
1889     ///
1890     /// \param other the other result object to convert
1891     /// \return reference to `(*this)`
1892     template<typename T2,
1893              typename E2,
1894              typename = typename std::enable_if<detail::result_is_move_convert_assignable<T, E, T2, E2>::value>::type>
1895     auto operator=(result<T2, E2>&& other) noexcept(
1896         std::is_nothrow_assignable<T, T2&&>::value&& std::is_nothrow_assignable<E, E2&&>::value) -> result&;
1897 
1898     /// \brief Perfect-forwarded assignment
1899     ///
1900     /// Depending on whether `*this` contains a value before the call, the
1901     /// contained value is either direct-initialized from std::forward<U>(value)
1902     /// or assigned from std::forward<U>(value).
1903     ///
1904     /// \note The function does not participate in overload resolution unless
1905     ///       - `std::decay_t<U>` is not a result type,
1906     ///       - `std::decay_t<U>` is not a failure type
1907     ///       - `std::is_nothrow_constructible_v<T, U>` is `true`
1908     ///       - `std::is_assignable_v<T&, U>` is `true`
1909     ///       - and at least one of the following is `true`:
1910     ///           - `T` is not a scalar type;
1911     ///           - `std::decay_t<U>` is not `T`.
1912     ///
1913     /// \param value to assign to the contained value
1914     /// \return reference to `(*this)`
1915     template<typename U, typename = typename std::enable_if<detail::result_is_value_assignable<T, U>::value>::type>
1916     auto operator=(U&& value) noexcept(std::is_nothrow_assignable<T, U>::value) -> result&;
1917 
1918     /// \{
1919     /// \brief Perfect-forwarded assignment
1920     ///
1921     /// Depending on whether `*this` contains an error before the call, the
1922     /// contained error is either direct-initialized via forwarding the error,
1923     /// or assigned from forwarding the error
1924     ///
1925     /// \note The function does not participate in overload resolution unless
1926     ///       - `std::is_nothrow_constructible_v<E, E2>` is `true`, and
1927     ///       - `std::is_assignable_v<E&, E2>` is `true`
1928     ///
1929     /// \param other the failure value to assign to this
1930     /// \return reference to `(*this)`
1931     template<typename E2,
1932              typename = typename std::enable_if<detail::result_is_failure_assignable<E, const E2&>::value>::type>
1933     auto operator=(const failure<E2>& other) noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
1934     template<typename E2,
1935              typename = typename std::enable_if<detail::result_is_failure_assignable<E, E2&&>::value>::type>
1936     auto operator=(failure<E2>&& other) noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
1937     /// \}
1938 
1939     //-------------------------------------------------------------------------
1940     // Observers
1941     //-------------------------------------------------------------------------
1942   public:
1943     /// \{
1944     /// \brief Retrieves a pointer to the contained value
1945     ///
1946     /// This operator exists to give `result` an `optional`-like API for cases
1947     /// where it's known that the `result` already contains a value.
1948     ///
1949     /// Care must be taken to ensure that this is only used in safe contexts
1950     /// where a `T` value is active.
1951     ///
1952     /// \note The behavior is undefined if `*this` does not contain a value.
1953     ///
1954     /// ### Examples
1955     ///
1956     /// Basic Usage:
1957     ///
1958     /// ```cpp
1959     /// auto r = cpp::result<Widget,int>{
1960     ///   make_widget()
1961     /// };
1962     ///
1963     /// r->do_something();
1964     /// ```
1965     ///
1966     /// \return a pointer to the contained value
1967     RESULT_WARN_UNUSED
1968     RESULT_CPP14_CONSTEXPR auto operator->() noexcept -> typename std::remove_reference<T>::type *;
1969     RESULT_WARN_UNUSED
1970     constexpr auto operator->() const noexcept ->
1971         typename std::remove_reference<typename std::add_const<T>::type>::type *;
1972     /// \}
1973 
1974     /// \{
1975     /// \brief Retrieves a reference to the contained value
1976     ///
1977     /// This operator exists to give `result` an `optional`-like API for cases
1978     /// where it's known that the `result` already contains a value.
1979     ///
1980     /// Care must be taken to ensure that this is only used in safe contexts
1981     /// where a `T` value is active.
1982     ///
1983     /// \note The behaviour is undefined if `*this` does not contain a value
1984     ///
1985     /// ### Examples
1986     ///
1987     /// Basic Usage:
1988     ///
1989     /// ```cpp
1990     /// auto r = cpp::result<Widget,int>{
1991     ///   make_widget()
1992     /// };
1993     ///
1994     /// (*r).do_something();
1995     ///
1996     /// consume(*r);
1997     /// ```
1998     ///
1999     /// \return a reference to the contained value
2000     RESULT_WARN_UNUSED
2001     RESULT_CPP14_CONSTEXPR auto operator*() & noexcept -> typename std::add_lvalue_reference<T>::type;
2002     RESULT_WARN_UNUSED
2003     RESULT_CPP14_CONSTEXPR auto operator*() && noexcept -> typename std::add_rvalue_reference<T>::type;
2004     RESULT_WARN_UNUSED
2005     constexpr auto operator*() const& noexcept ->
2006         typename std::add_lvalue_reference<typename std::add_const<T>::type>::type;
2007     RESULT_WARN_UNUSED
2008     constexpr auto operator*() const&& noexcept ->
2009         typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
2010     /// \}
2011 
2012     //-------------------------------------------------------------------------
2013 
2014     /// \brief Contextually convertible to `true` if `*this` contains a value
2015     ///
2016     /// This function exists to allow for simple, terse checks for containing
2017     /// a value.
2018     ///
2019     /// ### Examples
2020     ///
2021     /// Basic Usage:
2022     ///
2023     /// ```cpp
2024     /// auto get_result() -> cpp::result<int, int>;
2025     /// auto r = get_result();
2026     /// if (r) { ... }
2027     ///
2028     /// assert(static_cast<bool>(cpp::result<int,int>{42}));
2029     ///
2030     /// assert(!static_cast<bool>(cpp::result<int,int>{cpp::fail(42)}));
2031     /// ```
2032     ///
2033     /// \return `true` if `*this` contains a value, `false` if `*this`
2034     ///         does not contain a value
2035     RESULT_WARN_UNUSED
2036     constexpr explicit operator bool() const noexcept;
2037 
2038     /// \brief Returns `true` if `*this` contains a value
2039     ///
2040     /// ### Examples
2041     ///
2042     /// Basic Usage:
2043     ///
2044     /// ```cpp
2045     /// auto get_result() -> cpp::result<int, int>;
2046     /// auto r = get_result();
2047     /// if (r.has_value()) { ... }
2048     ///
2049     /// assert(cpp::result<int,int>{42}.has_value());
2050     ///
2051     /// assert(!cpp::result<int,int>{cpp::fail(42)}.has_value());
2052     /// ```
2053     ///
2054     /// \return `true` if `*this` contains a value, `false` if `*this`
2055     ///         contains an error
2056     RESULT_WARN_UNUSED
2057     constexpr auto has_value() const noexcept -> bool;
2058 
2059     /// \brief Returns `true` if `*this` contains an error
2060     ///
2061     /// ### Examples
2062     ///
2063     /// Basic Usage:
2064     ///
2065     /// ```cpp
2066     /// auto get_result() -> cpp::result<int, int>;
2067     ///
2068     /// auto r = get_result();
2069     /// if (r.has_error()) { ... }
2070     ///
2071     /// assert(!cpp::result<int,int>{42}.has_error());
2072     ///
2073     /// assert(cpp::result<int,int>{cpp::fail(42)}.has_error());
2074     /// ```
2075     ///
2076     /// \return `true` if `*this` contains an error, `false` if `*this`
2077     ///          contains a value
2078     RESULT_WARN_UNUSED
2079     constexpr auto has_error() const noexcept -> bool;
2080 
2081     //-------------------------------------------------------------------------
2082 
2083     /// \{
2084     /// \brief Returns a reference to the contained value
2085     ///
2086     /// This function provides checked (throwing) access to the underlying
2087     /// value. The constness and refness of this result is propagated to the
2088     /// underlying reference.
2089     ///
2090     /// If this contains an error, an exception is thrown containing the
2091     /// underlying error. The error is consumed propagating the same constness
2092     /// and refness of this result.
2093     ///
2094     /// ### Examples
2095     ///
2096     /// Basic Usage:
2097     ///
2098     /// ```cpp
2099     /// assert(cpp::result<int,int>{42}.value() == 42);
2100     ///
2101     /// auto r = cpp::result<std::unique_ptr<int>,int>{
2102     ///   std::make_unique<int>(42)
2103     /// };
2104     /// auto s = std::move(r).value();
2105     ///
2106     /// try {
2107     ///   auto r = cpp::result<int,int>{ cpp::fail(42) };
2108     ///   auto v = r.value();
2109     /// } catch (const cpp::bad_result_access<int>& e) {
2110     ///   assert(e.error() == 42);
2111     /// }
2112     /// ```
2113     ///
2114     /// \throws bad_result_access<E> if `*this` does not contain a value.
2115     ///
2116     /// \return the value of `*this`
2117     RESULT_WARN_UNUSED
2118     RESULT_CPP14_CONSTEXPR auto value() & -> typename std::add_lvalue_reference<T>::type;
2119     RESULT_WARN_UNUSED
2120     RESULT_CPP14_CONSTEXPR auto value() && -> typename std::add_rvalue_reference<T>::type;
2121     RESULT_WARN_UNUSED
2122     constexpr auto value() const& -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type;
2123     RESULT_WARN_UNUSED
2124     constexpr auto value() const&& -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
2125     /// \}
2126 
2127     /// \{
2128     /// \brief Returns the contained error, if one exists, or a
2129     ///        default-constructed error value
2130     ///
2131     /// The `error()` function will not throw any exceptions if `E` does not
2132     /// throw any exceptions for the copy or move construction.
2133     ///
2134     /// This is to limit the possible scope for exceptions, and to allow the
2135     /// error type to be treated as a "status"-like type, where the
2136     /// default-constructed case is considered the "good" state.
2137     ///
2138     /// If this function is invoked on an rvalue of a result, the error is
2139     /// returned via move-construction
2140     ///
2141     /// ### Requires
2142     ///
2143     /// * `std::is_default_constructible<E>::value` is `true`
2144     /// * `std::is_copy_constructible<E>::value` or
2145     ///   `std::is_move_constructible<E>::value` is `true`
2146     /// * `E{}` represents the "good" (non-error) state
2147     ///
2148     /// ### Examples
2149     ///
2150     /// Basic Usage:
2151     ///
2152     /// ```cpp
2153     /// auto r = cpp::result<int,std::error_code>{ 42 };
2154     /// assert(r.error() == std::error_code{});
2155     ///
2156     /// auto r = cpp::result<int,std::error_code>{
2157     ///   cpp::fail(std::io_errc::stream)
2158     /// };
2159     ///
2160     /// assert(r.error() == std::io_errc::stream);
2161     /// ```
2162     ///
2163     /// \return the error or a default-constructed error value
2164     RESULT_WARN_UNUSED
2165     constexpr auto
2166     error() const& noexcept(std::is_nothrow_constructible<E>::value&& std::is_nothrow_copy_constructible<E>::value)
2167         -> E;
2168     RESULT_WARN_UNUSED
2169     RESULT_CPP14_CONSTEXPR auto
2170     error() && noexcept(std::is_nothrow_constructible<E>::value&& std::is_nothrow_move_constructible<E>::value) -> E;
2171     /// }
2172 
2173     /// \{
2174     /// \brief Asserts an expectation that this result contains an error,
2175     ///        throwing a bad_result_access on failure
2176     ///
2177     /// If this function is invoked from an rvalue of `result`, then this will
2178     /// consume the underlying error first, if there is one.
2179     ///
2180     /// \note This function exists as a means to allow for results to be marked
2181     ///       `used` without requiring directly inspecting the underlying value.
2182     ///       This is, in effect, equivalent to `assert(res.has_value())`,
2183     ///       however it uses exceptions to ensure the stack can be unwound, and
2184     ///       exceptions invoked.
2185     ///
2186     /// ### Examples
2187     ///
2188     /// Basic Usage:
2189     ///
2190     /// ```cpp
2191     /// auto start_service() -> cpp::result<void,int>;
2192     ///
2193     /// start_service().expect("Service failed to start!");
2194     /// ```
2195     ///
2196     /// \param message the message to provide to this expectation
2197     template<typename String,
2198              typename = typename std::enable_if<(std::is_convertible<String, const std::string&>::value
2199                                                  && std::is_copy_constructible<E>::value)>::type>
2200     RESULT_CPP14_CONSTEXPR auto expect(String&& message) const& -> void;
2201     template<typename String,
2202              typename = typename std::enable_if<(std::is_convertible<String, const std::string&>::value
2203                                                  && std::is_move_constructible<E>::value)>::type>
2204     RESULT_CPP14_CONSTEXPR auto expect(String&& message) && -> void;
2205     /// \}
2206 
2207     //-------------------------------------------------------------------------
2208     // Monadic Functionalities
2209     //-------------------------------------------------------------------------
2210   public:
2211     /// \{
2212     /// \brief Returns the contained value if `*this` has a value,
2213     ///        otherwise returns \p default_value.
2214     ///
2215     /// ### Examples
2216     ///
2217     /// Basic Usage:
2218     ///
2219     /// ```cpp
2220     /// auto r = cpp::result<int,int>{42};
2221     /// assert(r.value_or(0) == 42);
2222     ///
2223     /// auto r = cpp::result<int,int>{cpp::fail(42)};
2224     /// assert(r.value_or(0) == 0);
2225     /// ```
2226     ///
2227     /// \param default_value the value to use in case `*this` contains an error
2228     /// \return the contained value or \p default_value
2229     template<typename U>
2230     RESULT_WARN_UNUSED constexpr auto value_or(U&& default_value) const& -> typename std::remove_reference<T>::type;
2231     template<typename U>
2232     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto value_or(U&& default_value) && ->
2233         typename std::remove_reference<T>::type;
2234     /// \}
2235 
2236     /// \{
2237     /// \brief Returns the contained error if `*this` has an error,
2238     ///        otherwise returns \p default_error.
2239     ///
2240     /// ### Examples
2241     ///
2242     /// Basic Usage:
2243     ///
2244     /// ```cpp
2245     /// auto r = cpp::result<int,int>{42};
2246     /// assert(r.error_or(0) == cpp::fail(0));
2247     ///
2248     /// auto r = cpp::result<int,int>{cpp::fail(42)};
2249     /// assert(r.error_or(0) == cpp::fail(42));
2250     /// ```
2251     ///
2252     /// \param default_error the error to use in case `*this` is empty
2253     /// \return the contained value or \p default_error
2254     template<typename U>
2255     RESULT_WARN_UNUSED constexpr auto error_or(U&& default_error) const& -> error_type;
2256     template<typename U>
2257     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error_or(U&& default_error) && -> error_type;
2258     /// \}
2259 
2260     //-------------------------------------------------------------------------
2261 
2262     /// \brief Returns a result containing \p value if this result contains
2263     ///        a value, otherwise returns a result containing the current
2264     ///        error.
2265     ///
2266     /// ### Examples
2267     ///
2268     /// Basic Usage:
2269     ///
2270     /// ```cpp
2271     /// auto r = cpp::result<int,int>{42};
2272     /// assert(r.and_then(100) == 100);
2273     ///
2274     /// auto r = cpp::result<int,int>{cpp::fail(42)};
2275     /// assert(r.and_then(100) == cpp::fail(42));
2276     /// ```
2277     ///
2278     /// \param value the value to return as a result
2279     /// \return a result of \p value if this contains a value
2280     template<typename U>
2281     RESULT_WARN_UNUSED constexpr auto and_then(U&& value) const -> result<typename std::decay<U>::type, E>;
2282 
2283     /// \{
2284     /// \brief Invokes the function \p fn with the value of this result as
2285     ///        the argument
2286     ///
2287     /// If this result contains an error, a result of the error is returned
2288     ///
2289     /// The function being called must return a `result` type or the program
2290     /// is ill-formed
2291     ///
2292     /// If this is called on an rvalue of `result` which contains an error,
2293     /// the returned `result` is constructed from an rvalue of that error.
2294     ///
2295     /// ### Examples
2296     ///
2297     /// Basic Usage:
2298     ///
2299     /// ```cpp
2300     /// auto to_string(int) -> cpp::result<std::string,int>;
2301     /// auto r = cpp::result<int,int>{42};
2302     /// assert(r.flat_map(to_string) == "42");
2303     ///
2304     /// auto r = cpp::result<int,int>{cpp::fail(42)};
2305     /// assert(r.flat_map(to_string) == cpp::fail(42));
2306     /// ```
2307     ///
2308     /// \param fn the function to invoke with this
2309     /// \return The result of the function being called
2310     template<typename Fn>
2311     RESULT_WARN_UNUSED constexpr auto flat_map(Fn&& fn) const& -> detail::invoke_result_t<Fn, const T&>;
2312     template<typename Fn>
2313     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn, T&&>;
2314     /// \}
2315 
2316     /// \{
2317     /// \brief Invokes the function \p fn with the value of this result as
2318     ///        the argument
2319     ///
2320     /// If this result is an error, the result of this function is that
2321     /// error. Otherwise this function wraps the result and returns it as an
2322     /// result.
2323     ///
2324     /// If this is called on an rvalue of `result` which contains an error,
2325     /// the returned `result` is constructed from an rvalue of that error.
2326     ///
2327     /// ### Examples
2328     ///
2329     /// Basic Usage:
2330     ///
2331     /// ```cpp
2332     /// auto to_string(int) -> std::string;
2333     /// auto r = cpp::result<int,int>{42};
2334     /// assert(r.map(to_string) == "42");
2335     ///
2336     /// auto r = cpp::result<int,int>{cpp::fail(42)};
2337     /// assert(r.map(to_string) == cpp::fail(42));
2338     /// ```
2339     ///
2340     /// \param fn the function to invoke with this
2341     /// \return The result result of the function invoked
2342     template<typename Fn>
2343     RESULT_WARN_UNUSED constexpr auto map(Fn&& fn) const& -> result<detail::invoke_result_t<Fn, const T&>, E>;
2344     template<typename Fn>
2345     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto map(Fn&& fn) && -> result<detail::invoke_result_t<Fn, T&&>, E>;
2346     /// \}
2347 
2348     /// \{
2349     /// \brief Invokes the function \p fn with the error of this result as
2350     ///        the argument
2351     ///
2352     /// If this result contains a value, the result of this function is that
2353     /// value. Otherwise the function is called with that error and returns the
2354     /// result as a result.
2355     ///
2356     /// If this is called on an rvalue of `result` which contains a value,
2357     /// the returned `result` is constructed from an rvalue of that value.
2358     ///
2359     /// ### Examples
2360     ///
2361     /// Basic Usage:
2362     ///
2363     /// ```cpp
2364     /// auto to_string(int) -> std::string;
2365     /// auto r = cpp::result<int,int>{42};
2366     /// assert(r.map_error(to_string) == 42);
2367     ///
2368     /// auto r = cpp::result<int,int>{cpp::fail(42)};
2369     /// assert(r.map_error(to_string) == cpp::fail("42"));
2370     ///
2371     /// auto r = cpp::result<std::string,int>{};
2372     /// auto s = r.map(std::string::size); // 's' contains 'result<size_t,int>'
2373     /// ```
2374     ///
2375     /// \param fn the function to invoke with this
2376     /// \return The result result of the function invoked
2377     template<typename Fn>
2378     RESULT_WARN_UNUSED constexpr auto map_error(Fn&& fn) const& -> result<T, detail::invoke_result_t<Fn, const E&>>;
2379     template<typename Fn>
2380     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto map_error(Fn&& fn) && -> result<T, detail::invoke_result_t<Fn, E&&>>;
2381     /// \}
2382 
2383     /// \{
2384     /// \brief Invokes the function \p fn with the error of this result as
2385     ///        the argument
2386     ///
2387     /// If this result contains a value, a result of the value is returned
2388     ///
2389     /// The function being called must return a `result` type or the program
2390     /// is ill-formed
2391     ///
2392     /// If this is called on an rvalue of `result` which contains an error,
2393     /// the returned `result` is constructed from an rvalue of that error.
2394     ///
2395     /// ### Examples
2396     ///
2397     /// Basic Usage:
2398     ///
2399     /// ```cpp
2400     /// auto to_string(int) -> cpp::result<int,std::string>;
2401     /// auto r = cpp::result<int,int>{42};
2402     /// assert(r.flat_map(to_string) == 42);
2403     ///
2404     /// auto r = cpp::result<int,int>{cpp::fail(42)};
2405     /// assert(r.flat_map(to_string) == cpp::fail("42"));
2406     /// ```
2407     ///
2408     /// \param fn the function to invoke with this
2409     /// \return The result of the function being called
2410     template<typename Fn>
2411     RESULT_WARN_UNUSED constexpr auto flat_map_error(Fn&& fn) const& -> detail::invoke_result_t<Fn, const E&>;
2412     template<typename Fn>
2413     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn&& fn) && -> detail::invoke_result_t<Fn, E&&>;
2414     /// \}
2415 
2416     //-------------------------------------------------------------------------
2417     // Private Members
2418     //-------------------------------------------------------------------------
2419   private:
2420     detail::result_storage<T, E> m_storage;
2421 
2422     //-------------------------------------------------------------------------
2423     // Private Monadic Functions
2424     //-------------------------------------------------------------------------
2425   private:
2426     /// \{
2427     /// \brief Map implementations for void and non-void functions
2428     ///
2429     /// \param fn the function
2430     template<typename Fn>
2431     constexpr auto map_impl(std::true_type, Fn&& fn) const& -> result<void, E>;
2432     template<typename Fn>
2433     constexpr auto map_impl(std::false_type, Fn&& fn) const& -> result<detail::invoke_result_t<Fn, const T&>, E>;
2434     template<typename Fn>
2435     RESULT_CPP14_CONSTEXPR auto map_impl(std::true_type, Fn&& fn) && -> result<void, E>;
2436     template<typename Fn>
2437     RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn, T&&>, E>;
2438     /// \}
2439 };
2440 
2441 //===========================================================================
2442 // class : result<void,E>
2443 //===========================================================================
2444 
2445 /////////////////////////////////////////////////////////////////////////////
2446 /// \brief Partial specialization of `result<void, E>`
2447 ///
2448 /// \tparam E the underlying error type
2449 /////////////////////////////////////////////////////////////////////////////
2450 template<typename E>
2451 class RESULT_NODISCARD result<void, E> {
2452     // Type requirements
2453 
2454     static_assert(!std::is_void<typename std::decay<E>::type>::value,
2455                   "It is ill-formed for E to be (possibly CV-qualified) void type");
2456     static_assert(!std::is_abstract<E>::value, "It is ill-formed for E to be abstract type");
2457     static_assert(!is_failure<typename std::decay<E>::type>::value,
2458                   "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type");
2459     static_assert(!std::is_reference<E>::value,
2460                   "It is ill-formed for E to be a reference type. "
2461                   "Only T types may be lvalue references");
2462 
2463     // Friendship
2464 
2465     friend detail::result_error_extractor;
2466 
2467     template<typename T2, typename E2>
2468     friend class result;
2469 
2470     //-------------------------------------------------------------------------
2471     // Public Member Types
2472     //-------------------------------------------------------------------------
2473   public:
2474     using value_type = void; ///< The value type of this result
2475     using error_type = E; ///< The error type of this result
2476     using failure_type = failure<E>; ///< The failure type
2477 
2478     template<typename U>
2479     using rebind = result<U, E>; ///< Rebinds the result type
2480 
2481     //-------------------------------------------------------------------------
2482     // Constructor / Assignment
2483     //-------------------------------------------------------------------------
2484   public:
2485     /// \brief Constructs a `result` object in a value state
2486     ///
2487     /// ### Examples
2488     ///
2489     /// Basic Usage:
2490     ///
2491     /// ```cpp
2492     /// auto r = cpp::result<void,int>{};
2493     /// ```
2494     constexpr result() noexcept;
2495 
2496     /// \brief Copy constructs this result
2497     ///
2498     /// If other contains an error, constructs an object that contains a copy
2499     /// of that error.
2500     ///
2501     /// \note This constructor is defined as deleted if
2502     ///       `std::is_copy_constructible<E>::value` is `false`
2503     ///
2504     /// \note This constructor is defined as trivial if both
2505     ///       `std::is_trivially_copy_constructible<E>::value` are `true`
2506     ///
2507     /// ### Examples
2508     ///
2509     /// Basic Usage:
2510     ///
2511     /// ```cpp
2512     /// const auto r = cpp::result<void,int>{};
2513     /// const auto s = r;
2514     /// ```
2515     ///
2516     /// \param other the result to copy
2517     constexpr result(const result& other) = default;
2518 
2519     /// \brief Move constructs a result
2520     ///
2521     /// If other contains an error, move-constructs this result from that
2522     /// error.
2523     ///
2524     /// \note This constructor is defined as deleted if
2525     ///       `std::is_move_constructible<E>::value` is `false`
2526     ///
2527     /// \note This constructor is defined as trivial if both
2528     ///       `std::is_trivially_move_constructible<E>::value` are `true`
2529     ///
2530     /// ### Examples
2531     ///
2532     /// Basic Usage:
2533     ///
2534     /// ```cpp
2535     /// auto r = cpp::result<void,std::string>{};
2536     /// auto s = std::move(r);
2537     /// ```
2538     ///
2539     /// \param other the result to move
2540     constexpr result(result&& other) = default;
2541 
2542     /// \brief Converting copy constructor
2543     ///
2544     /// If \p other contains a value, constructs a result object that is not
2545     /// in an error state -- ignoring the value.
2546     ///
2547     /// If \p other contains an error, constructs a result object that
2548     /// contains an error, initialized as if direct-initializing
2549     /// (but not direct-list-initializing) an object of type `E`.
2550     ///
2551     /// \note This constructor does not participate in overload resolution
2552     ///       unless the following conditions are met:
2553     ///       - `std::is_constructible_v<E, const E2&>` is `true`
2554     ///
2555     /// ### Examples
2556     ///
2557     /// Basic Usage:
2558     ///
2559     /// ```cpp
2560     /// const auto r = cpp::result<int,int>{42};
2561     /// const auto s = cpp::result<void,int>{r};
2562     /// ```
2563     ///
2564     /// \param other the other type to convert
2565     template<typename U, typename E2, typename = typename std::enable_if<std::is_constructible<E, E2>::value>::type>
2566     explicit result(const result<U, E2>& other) noexcept(std::is_nothrow_constructible<E, const E2&>::value);
2567 
2568     /// \brief Converting move constructor
2569     ///
2570     /// If \p other contains an error, constructs a result object that
2571     /// contains an error, initialized as if direct-initializing
2572     /// (but not direct-list-initializing) an object of type E&&.
2573     ///
2574     /// \note This constructor does not participate in overload resolution
2575     ///       unless the following conditions are met:
2576     ///       - `std::is_constructible_v<E, const E2&>` is `true`
2577     ///
2578     /// ### Examples
2579     ///
2580     /// Basic Usage:
2581     ///
2582     /// ```cpp
2583     /// auto r = cpp::result<int,std::string>{42};
2584     /// auto s = cpp::result<void,std::string>{
2585     ///   std::move(r)
2586     /// };
2587     /// ```
2588     ///
2589     /// \param other the other type to convert
2590     template<typename U, typename E2, typename = typename std::enable_if<std::is_constructible<E, E2>::value>::type>
2591     explicit result(result<U, E2>&& other) noexcept(std::is_nothrow_constructible<E, E2&&>::value);
2592 
2593     //-------------------------------------------------------------------------
2594 
2595     /// \brief Constructs a result object in a value state
2596     ///
2597     /// This constructor exists primarily for symmetry with the `result<T,E>`
2598     /// constructor. Unlike the `T` overload, no variadic arguments may be
2599     /// supplied.
2600     ///
2601     /// ### Examples
2602     ///
2603     /// Basic Usage:
2604     ///
2605     /// ```cpp
2606     /// auto r = cpp::result<void,std::string>{cpp::in_place};
2607     /// ```
2608     constexpr explicit result(in_place_t) noexcept;
2609 
2610     /// \brief Constructs a result object that contains an error
2611     ///
2612     /// the value is initialized as if direct-initializing (but not
2613     /// direct-list-initializing) an object of type `E` from the arguments
2614     /// `std::forward<Args>(args)...`
2615     ///
2616     /// ### Examples
2617     ///
2618     /// Basic Usage:
2619     ///
2620     /// ```cpp
2621     /// auto r = cpp::result<void,std::string>{
2622     ///   cpp::in_place_error, "Hello world"
2623     /// };
2624     /// ```
2625     ///
2626     /// \param args the arguments to pass to `E`'s constructor
2627     template<typename... Args, typename = typename std::enable_if<std::is_constructible<E, Args...>::value>::type>
2628     constexpr explicit result(in_place_error_t,
2629                               Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value);
2630 
2631     /// \brief Constructs a result object that contains an error
2632     ///
2633     /// The value is initialized as if direct-initializing (but not
2634     /// direct-list-initializing) an object of type `E` from the arguments
2635     /// `std::forward<std::initializer_list<U>>(ilist)`,
2636     /// `std::forward<Args>(args)...`
2637     ///
2638     /// ### Examples
2639     ///
2640     /// Basic Usage:
2641     ///
2642     /// ```cpp
2643     /// auto r = cpp::result<void,std::string>{
2644     ///   cpp::in_place_error, {'H','e','l','l','o'}
2645     /// };
2646     /// ```
2647     ///
2648     /// \param ilist An initializer list of entries to forward
2649     /// \param args  the arguments to pass to Es constructor
2650     template<
2651         typename U,
2652         typename... Args,
2653         typename = typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
2654     constexpr explicit result(in_place_error_t, std::initializer_list<U> ilist, Args&&...args) noexcept(
2655         std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value);
2656 
2657     //-------------------------------------------------------------------------
2658 
2659     /// \{
2660     /// \brief Constructs the underlying error of this result
2661     ///
2662     /// \note This constructor only participates in overload resolution if
2663     ///       `E` is constructible from \p e
2664     ///
2665     /// ### Examples
2666     ///
2667     /// Basic Usage:
2668     ///
2669     /// ```cpp
2670     /// cpp::result<void,int> r = cpp::fail(42);
2671     ///
2672     /// auto get_error_result() -> cpp::result<void,std::string> {
2673     ///   return cpp::fail("hello world!");
2674     /// }
2675     /// ```
2676     ///
2677     /// \param e the failure error
2678     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, const E2&>::value>::type>
2679     constexpr /* implicit */ result(const failure<E2>& e) noexcept(std::is_nothrow_constructible<E, const E2&>::value);
2680     template<typename E2, typename = typename std::enable_if<std::is_constructible<E, E2&&>::value>::type>
2681     constexpr /* implicit */ result(failure<E2>&& e) noexcept(std::is_nothrow_constructible<E, E2&&>::value);
2682     /// \}
2683 
2684     //-------------------------------------------------------------------------
2685 
2686     /// \brief Copy assigns the result stored in \p other
2687     ///
2688     /// \note The function does not participate in overload resolution unless
2689     ///       - `std::is_nothrow_copy_constructible_v<E>` is `true`
2690     ///       this restriction guarantees that no 'valueless_by_exception` state
2691     ///       may occur.
2692     ///
2693     /// \note This assignment operator is defined as trivial if the following
2694     ///       conditions are all `true`:
2695     ///       - `std::is_trivially_copy_constructible<E>::value`
2696     ///       - `std::is_trivially_copy_assignable<E>::value`
2697     ///       - `std::is_trivially_destructible<E>::value`
2698     ///
2699     /// \param other the other result to copy
2700     auto operator=(const result& other) -> result& = default;
2701 
2702     /// \brief Move assigns the result stored in \p other
2703     ///
2704     /// \note The function does not participate in overload resolution unless
2705     ///       - `std::is_nothrow_copy_constructible_v<E>` is `true`
2706     ///       this restriction guarantees that no 'valueless_by_exception` state
2707     ///       may occur.
2708     ///
2709     /// \note This assignment operator is defined as trivial if the following
2710     ///       conditions are all `true`:
2711     ///       - `std::is_trivially_move_constructible<E>::value`
2712     ///       - `std::is_trivially_move_assignable<E>::value`
2713     ///       - `std::is_trivially_destructible<E>::value`
2714     ///
2715     /// \param other the other result to copy
2716     auto operator=(result&& other) -> result& = default;
2717 
2718     /// \brief Copy-converts the state of \p other
2719     ///
2720     /// If both this and \p other contain an error, the underlying error is
2721     /// assigned through copy-assignment.
2722     ///
2723     /// If \p other contains a value state, this result is constructed in a
2724     /// value state.
2725     ///
2726     /// If \p other contans an error state, and this contains a value state,
2727     /// the underlying error is constructed through copy-construction.
2728     ///
2729     /// \note The function does not participate in overload resolution unless
2730     ///       - `std::is_nothrow_constructible_v<E, const E2&>`,
2731     ///         `std::is_assignable_v<E&, const E2&>` are all `true`.
2732     ///
2733     /// \param other the other result object to convert
2734     /// \return reference to `(*this)`
2735     template<typename E2,
2736              typename = typename std::enable_if<std::is_nothrow_constructible<E, const E2&>::value
2737                                                 && std::is_assignable<E&, const E2&>::value>::type>
2738     auto operator=(const result<void, E2>& other) noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
2739 
2740     /// \brief Move-converts the state of \p other
2741     ///
2742     /// If both this and \p other contain an error, the underlying error is
2743     /// assigned through move-assignment.
2744     ///
2745     /// If \p other contains a value state, this result is constructed in a
2746     /// value state.
2747     ///
2748     /// If \p other contans an error state, and this contains a value state,
2749     /// the underlying error is constructed through move-construction.
2750     ///
2751     /// \note The function does not participate in overload resolution unless
2752     ///       - `std::is_nothrow_constructible_v<E, E2&&>`,
2753     ///         `std::is_assignable_v<E&, E2&&>` are all `true`.
2754     ///
2755     /// \param other the other result object to convert
2756     /// \return reference to `(*this)`
2757     template<typename E2,
2758              typename = typename std::enable_if<std::is_nothrow_constructible<E, E2&&>::value
2759                                                 && std::is_assignable<E&, E2&&>::value>::type>
2760     auto operator=(result<void, E2>&& other) noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
2761 
2762     /// \{
2763     /// \brief Perfect-forwarded assignment
2764     ///
2765     /// Depending on whether `*this` contains an error before the call, the
2766     /// contained error is either direct-initialized via forwarding the error,
2767     /// or assigned from forwarding the error
2768     ///
2769     /// \note The function does not participate in overload resolution unless
2770     ///       - `std::is_nothrow_constructible_v<E, E2>` is `true`, and
2771     ///       - `std::is_assignable_v<E&, E2>` is `true`
2772     ///
2773     /// \param other the failure value to assign to this
2774     /// \return reference to `(*this)`
2775     template<typename E2,
2776              typename = typename std::enable_if<detail::result_is_failure_assignable<E, const E2&>::value>::type>
2777     auto operator=(const failure<E2>& other) noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
2778     template<typename E2,
2779              typename = typename std::enable_if<detail::result_is_failure_assignable<E, E2&&>::value>::type>
2780     auto operator=(failure<E2>&& other) noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
2781     /// \}
2782 
2783     //-------------------------------------------------------------------------
2784     // Observers
2785     //-------------------------------------------------------------------------
2786   public:
2787     /// \brief Contextually convertible to `true` if `*this` does not contain
2788     ///        an error
2789     ///
2790     /// This function exists to allow for simple, terse checks for containing
2791     /// a value.
2792     ///
2793     /// ### Examples
2794     ///
2795     /// Basic Usage:
2796     ///
2797     /// ```cpp
2798     /// auto get_result() -> cpp::result<void, int>;
2799     /// auto r = get_result();
2800     /// if (r) { ... }
2801     ///
2802     /// assert(static_cast<bool>(cpp::result<void,int>{}));
2803     ///
2804     /// assert(!static_cast<bool>(cpp::result<void,int>{cpp::fail(42)}));
2805     /// ```
2806     ///
2807     /// \return `true` if `*this` contains a value, `false` if `*this`
2808     ///         does not contain a value
2809     RESULT_WARN_UNUSED
2810     constexpr explicit operator bool() const noexcept;
2811 
2812     /// \copydoc result<T,E>::has_value
2813     RESULT_WARN_UNUSED
2814     constexpr auto has_value() const noexcept -> bool;
2815 
2816     /// \copydoc result<T,E>::has_error
2817     RESULT_WARN_UNUSED
2818     constexpr auto has_error() const noexcept -> bool;
2819 
2820     //-------------------------------------------------------------------------
2821 
2822     /// \{
2823     /// \brief Throws an exception if `(*this)` is in an error state
2824     ///
2825     /// This function exists for symmetry with `cpp::result<T,E>` objects where
2826     /// `T` contains a value.
2827     ///
2828     /// If this contains an error, an exception is thrown containing the
2829     /// underlying error. The error is consumed propagating the same constness
2830     /// and refness of this result.
2831     ///
2832     /// ### Examples
2833     ///
2834     /// Basic Usage:
2835     ///
2836     /// ```cpp
2837     /// cpp::result<void,int>{}.value(); // no exception
2838     ///
2839     /// auto r = cpp::result<void,std::unique_ptr<int>>{
2840     ///   cpp::fail(std::make_unique<int>(42))
2841     /// };
2842     /// std::move(r).value(); // throws bad_result_access<std::unique_ptr<int>>
2843     ///
2844     /// try {
2845     ///   auto r = cpp::result<void,int>{ cpp::fail(42) }.value();
2846     /// } catch (const cpp::bad_result_access<int>& e) {
2847     ///   assert(e.error() == 42);
2848     /// }
2849     /// ```
2850     ///
2851     /// \throws bad_result_access<E> if `*this` does not contain a value.
2852     RESULT_CPP14_CONSTEXPR auto value() && -> void;
2853     RESULT_CPP14_CONSTEXPR auto value() const& -> void;
2854     /// \}
2855 
2856     /// \{
2857     /// \copydoc result<T,E>::error
2858     RESULT_WARN_UNUSED
2859     constexpr auto
2860     error() const& noexcept(std::is_nothrow_constructible<E>::value&& std::is_nothrow_copy_constructible<E>::value)
2861         -> E;
2862     RESULT_WARN_UNUSED
2863     RESULT_CPP14_CONSTEXPR auto
2864     error() && noexcept(std::is_nothrow_constructible<E>::value&& std::is_nothrow_copy_constructible<E>::value) -> E;
2865     /// \}
2866 
2867     /// \{
2868     /// \copydoc result<T,E>::expect
2869     template<typename String,
2870              typename = typename std::enable_if<(std::is_convertible<String, const std::string&>::value
2871                                                  && std::is_copy_constructible<E>::value)>::type>
2872     RESULT_CPP14_CONSTEXPR auto expect(String&& message) const& -> void;
2873     template<typename String,
2874              typename = typename std::enable_if<(std::is_convertible<String, const std::string&>::value
2875                                                  && std::is_move_constructible<E>::value)>::type>
2876     RESULT_CPP14_CONSTEXPR auto expect(String&& message) && -> void;
2877     /// \}
2878 
2879     //-------------------------------------------------------------------------
2880     // Monadic Functionalities
2881     //-------------------------------------------------------------------------
2882   public:
2883     /// \{
2884     /// \copydoc result<T,E>::error_or
2885     template<typename U>
2886     RESULT_WARN_UNUSED constexpr auto error_or(U&& default_error) const& -> error_type;
2887     template<typename U>
2888     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error_or(U&& default_error) && -> error_type;
2889     /// \}
2890 
2891     //-------------------------------------------------------------------------
2892 
2893     /// \copydoc result<T,E>::and_then
2894     template<typename U>
2895     RESULT_WARN_UNUSED constexpr auto and_then(U&& value) const -> result<typename std::decay<U>::type, E>;
2896 
2897     /// \{
2898     /// \brief Invokes the function \p fn if `(*this)` contains no value
2899     ///
2900     /// If this result contains an error, a result of the error is returned
2901     ///
2902     /// The function being called must return a `result` type or the program
2903     /// is ill-formed
2904     ///
2905     /// If this is called on an rvalue of `result` which contains an error,
2906     /// the returned `result` is constructed from an rvalue of that error.
2907     ///
2908     /// ### Examples
2909     ///
2910     /// Basic Usage:
2911     ///
2912     /// ```cpp
2913     /// auto generate_int() -> cpp::result<int,int> { return 42; }
2914     /// auto r = cpp::result<void,int>{};
2915     /// assert(r.flat_map(generate_int) == 42);
2916     ///
2917     /// auto r = cpp::result<void,int>{cpp::fail(42)};
2918     /// assert(r.flat_map(generate_int) == cpp::fail(42));
2919     /// ```
2920     ///
2921     /// \param fn the function to invoke with this
2922     /// \return The result of the function being called
2923     template<typename Fn>
2924     RESULT_WARN_UNUSED constexpr auto flat_map(Fn&& fn) const& -> detail::invoke_result_t<Fn>;
2925     template<typename Fn>
2926     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn>;
2927     /// \}
2928 
2929     /// \{
2930     /// \brief Invokes the function \p fn if `(*this)` contains no value
2931     ///
2932     /// If this result is an error, the result of this function is that
2933     /// error. Otherwise this function wraps the result and returns it as an
2934     /// result.
2935     ///
2936     /// If this is called on an rvalue of `result` which contains an error,
2937     /// the returned `result` is constructed from an rvalue of that error.
2938     ///
2939     /// ### Examples
2940     ///
2941     /// Basic Usage:
2942     ///
2943     /// ```cpp
2944     /// auto generate_int() -> int { return 42; }
2945     /// auto r = cpp::result<void,int>{};
2946     /// assert(r.map(generate_int) == 42);
2947     ///
2948     /// auto r = cpp::result<void,int>{cpp::fail(42)};
2949     /// assert(r.map(generate_int) == cpp::fail(42));
2950     /// ```
2951     ///
2952     /// \param fn the function to invoke with this
2953     /// \return The result result of the function invoked
2954     template<typename Fn>
2955     RESULT_WARN_UNUSED constexpr auto map(Fn&& fn) const& -> result<detail::invoke_result_t<Fn>, E>;
2956     template<typename Fn>
2957     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto map(Fn&& fn) && -> result<detail::invoke_result_t<Fn>, E>;
2958     /// \}
2959 
2960     /// \{
2961     /// \copydoc result<T,E>::map_error
2962     template<typename Fn>
2963     constexpr auto map_error(Fn&& fn) const& -> result<void, detail::invoke_result_t<Fn, const E&>>;
2964     template<typename Fn>
2965     RESULT_CPP14_CONSTEXPR auto map_error(Fn&& fn) && -> result<void, detail::invoke_result_t<Fn, E&&>>;
2966     /// \}
2967 
2968     /// \{
2969     /// \copydoc result<T,E>::flat_map_error
2970     template<typename Fn>
2971     RESULT_WARN_UNUSED constexpr auto flat_map_error(Fn&& fn) const& -> detail::invoke_result_t<Fn, const E&>;
2972     template<typename Fn>
2973     RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn&& fn) && -> detail::invoke_result_t<Fn, E&&>;
2974     /// \}
2975 
2976     //-------------------------------------------------------------------------
2977     // Private Members
2978     //-------------------------------------------------------------------------
2979   private:
2980     detail::result_storage<detail::unit, E> m_storage;
2981 
2982     //-------------------------------------------------------------------------
2983     // Private Monadic Functions
2984     //-------------------------------------------------------------------------
2985   private:
2986     /// \{
2987     /// \brief Map implementations for void and non-void functions
2988     ///
2989     /// \param fn the function
2990     template<typename Fn>
2991     constexpr auto map_impl(std::true_type, Fn&& fn) const& -> result<void, E>;
2992     template<typename Fn>
2993     constexpr auto map_impl(std::false_type, Fn&& fn) const& -> result<detail::invoke_result_t<Fn>, E>;
2994     template<typename Fn>
2995     RESULT_CPP14_CONSTEXPR auto map_impl(std::true_type, Fn&& fn) && -> result<void, E>;
2996     template<typename Fn>
2997     RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn>, E>;
2998     /// \}
2999 };
3000 
3001 //===========================================================================
3002 // non-member functions : class : result
3003 //===========================================================================
3004 
3005 //---------------------------------------------------------------------------
3006 // Comparison
3007 //---------------------------------------------------------------------------
3008 
3009 template<typename T1, typename E1, typename T2, typename E2>
3010 constexpr auto operator==(const result<T1, E1>& lhs, const result<T2, E2>& rhs) noexcept -> bool;
3011 template<typename T1, typename E1, typename T2, typename E2>
3012 constexpr auto operator!=(const result<T1, E1>& lhs, const result<T2, E2>& rhs) noexcept -> bool;
3013 template<typename T1, typename E1, typename T2, typename E2>
3014 constexpr auto operator>=(const result<T1, E1>& lhs, const result<T2, E2>& rhs) noexcept -> bool;
3015 template<typename T1, typename E1, typename T2, typename E2>
3016 constexpr auto operator<=(const result<T1, E1>& lhs, const result<T2, E2>& rhs) noexcept -> bool;
3017 template<typename T1, typename E1, typename T2, typename E2>
3018 constexpr auto operator>(const result<T1, E1>& lhs, const result<T2, E2>& rhs) noexcept -> bool;
3019 template<typename T1, typename E1, typename T2, typename E2>
3020 constexpr auto operator<(const result<T1, E1>& lhs, const result<T2, E2>& rhs) noexcept -> bool;
3021 
3022 //---------------------------------------------------------------------------
3023 
3024 template<typename E1, typename E2>
3025 constexpr auto operator==(const result<void, E1>& lhs, const result<void, E2>& rhs) noexcept -> bool;
3026 template<typename E1, typename E2>
3027 constexpr auto operator!=(const result<void, E1>& lhs, const result<void, E2>& rhs) noexcept -> bool;
3028 template<typename E1, typename E2>
3029 constexpr auto operator>=(const result<void, E1>& lhs, const result<void, E2>& rhs) noexcept -> bool;
3030 template<typename E1, typename E2>
3031 constexpr auto operator<=(const result<void, E1>& lhs, const result<void, E2>& rhs) noexcept -> bool;
3032 template<typename E1, typename E2>
3033 constexpr auto operator>(const result<void, E1>& lhs, const result<void, E2>& rhs) noexcept -> bool;
3034 template<typename E1, typename E2>
3035 constexpr auto operator<(const result<void, E1>& lhs, const result<void, E2>& rhs) noexcept -> bool;
3036 
3037 //---------------------------------------------------------------------------
3038 
3039 template<typename T, typename E, typename U, typename = typename std::enable_if<!std::is_same<T, void>::value>::type>
3040 constexpr auto operator==(const result<T, E>& exp, const U& value) noexcept -> bool;
3041 template<typename T, typename U, typename E, typename = typename std::enable_if<!std::is_same<U, void>::value>::type>
3042 constexpr auto operator==(const T& value, const result<U, E>& exp) noexcept -> bool;
3043 template<typename T, typename E, typename U, typename = typename std::enable_if<!std::is_same<T, void>::value>::type>
3044 constexpr auto operator!=(const result<T, E>& exp, const U& value) noexcept -> bool;
3045 template<typename T, typename U, typename E, typename = typename std::enable_if<!std::is_same<U, void>::value>::type>
3046 constexpr auto operator!=(const T& value, const result<U, E>& exp) noexcept -> bool;
3047 template<typename T, typename E, typename U, typename = typename std::enable_if<!std::is_same<T, void>::value>::type>
3048 constexpr auto operator<=(const result<T, E>& exp, const U& value) noexcept -> bool;
3049 template<typename T, typename U, typename E, typename = typename std::enable_if<!std::is_same<U, void>::value>::type>
3050 constexpr auto operator<=(const T& value, const result<U, E>& exp) noexcept -> bool;
3051 template<typename T, typename E, typename U, typename = typename std::enable_if<!std::is_same<T, void>::value>::type>
3052 constexpr auto operator>=(const result<T, E>& exp, const U& value) noexcept -> bool;
3053 template<typename T, typename U, typename E, typename = typename std::enable_if<!std::is_same<U, void>::value>::type>
3054 constexpr auto operator>=(const T& value, const result<U, E>& exp) noexcept -> bool;
3055 template<typename T, typename E, typename U, typename = typename std::enable_if<!std::is_same<T, void>::value>::type>
3056 constexpr auto operator<(const result<T, E>& exp, const U& value) noexcept -> bool;
3057 template<typename T, typename U, typename E, typename = typename std::enable_if<!std::is_same<U, void>::value>::type>
3058 constexpr auto operator<(const T& value, const result<U, E>& exp) noexcept -> bool;
3059 template<typename T, typename E, typename U, typename = typename std::enable_if<!std::is_same<T, void>::value>::type>
3060 constexpr auto operator>(const result<T, E>& exp, const U& value) noexcept -> bool;
3061 template<typename T, typename U, typename E, typename = typename std::enable_if<!std::is_same<U, void>::value>::type>
3062 constexpr auto operator>(const T& value, const result<U, E>& exp) noexcept -> bool;
3063 
3064 //---------------------------------------------------------------------------
3065 
3066 template<typename T, typename E, typename U>
3067 constexpr auto operator==(const result<T, E>& exp, const failure<U>& value) noexcept -> bool;
3068 template<typename T, typename U, typename E>
3069 constexpr auto operator==(const failure<T>& value, const result<E, U>& exp) noexcept -> bool;
3070 template<typename T, typename E, typename U>
3071 constexpr auto operator!=(const result<T, E>& exp, const failure<U>& value) noexcept -> bool;
3072 template<typename T, typename U, typename E>
3073 constexpr auto operator!=(const failure<T>& value, const result<E, U>& exp) noexcept -> bool;
3074 template<typename T, typename E, typename U>
3075 constexpr auto operator<=(const result<T, E>& exp, const failure<U>& value) noexcept -> bool;
3076 template<typename T, typename U, typename E>
3077 constexpr auto operator<=(const failure<T>& value, const result<E, U>& exp) noexcept -> bool;
3078 template<typename T, typename E, typename U>
3079 constexpr auto operator>=(const result<T, E>& exp, const failure<U>& value) noexcept -> bool;
3080 template<typename T, typename U, typename E>
3081 constexpr auto operator>=(const failure<T>& value, const result<E, U>& exp) noexcept -> bool;
3082 template<typename T, typename E, typename U>
3083 constexpr auto operator<(const result<T, E>& exp, const failure<U>& value) noexcept -> bool;
3084 template<typename T, typename U, typename E>
3085 constexpr auto operator<(const failure<T>& value, const result<E, U>& exp) noexcept -> bool;
3086 template<typename T, typename E, typename U>
3087 constexpr auto operator>(const result<T, E>& exp, const failure<U>& value) noexcept -> bool;
3088 template<typename T, typename U, typename E>
3089 constexpr auto operator>(const failure<T>& value, const result<E, U>& exp) noexcept -> bool;
3090 
3091 //---------------------------------------------------------------------------
3092 // Utilities
3093 //---------------------------------------------------------------------------
3094 
3095 /// \{
3096 /// \brief Swaps the contents of \p lhs with \p rhs
3097 ///
3098 /// \param lhs the left result
3099 /// \param rhs the right result
3100 template<typename T, typename E>
3101 auto swap(result<T, E>& lhs, result<T, E>& rhs)
3102 #if __cplusplus >= 201703L
3103     noexcept(
3104         std::is_nothrow_move_constructible<result<T, E>>::value&& std::is_nothrow_move_assignable<result<T, E>>::value&&
3105             std::is_nothrow_swappable<T>::value&& std::is_nothrow_swappable<E>::value)
3106 #else
3107     noexcept(
3108         std::is_nothrow_move_constructible<result<T, E>>::value&& std::is_nothrow_move_assignable<result<T, E>>::value)
3109 #endif
3110         -> void;
3111 template<typename E>
3112 auto swap(result<void, E>& lhs, result<void, E>& rhs)
3113 #if __cplusplus >= 201703L
3114     noexcept(std::is_nothrow_move_constructible<result<void, E>>::value&&
3115                  std::is_nothrow_move_assignable<result<void, E>>::value&& std::is_nothrow_swappable<E>::value)
3116 #else
3117     noexcept(std::is_nothrow_move_constructible<result<void, E>>::value&&
3118                  std::is_nothrow_move_assignable<result<void, E>>::value)
3119 #endif
3120         -> void;
3121 /// \}
3122 
3123 } // namespace bitwizeshift
3124 } // namespace RESULT_NAMESPACE_INTERNAL
3125 
3126 namespace std {
3127 
3128 template<typename T, typename E>
3129 struct hash<::RESULT_NS_IMPL::result<T, E>> {
3130     auto operator()(const RESULT_NS_IMPL::result<T, E>& x) const -> std::size_t
3131     {
3132         if (x.has_value()) {
3133             return std::hash<T>{}(*x) + 1; // add '1' to differentiate from error case
3134         }
3135         return std::hash<E>{}(::RESULT_NS_IMPL::detail::extract_error(x));
3136     }
3137 };
3138 
3139 template<typename E>
3140 struct hash<::RESULT_NS_IMPL::result<void, E>> {
3141     auto operator()(const RESULT_NS_IMPL::result<void, E>& x) const -> std::size_t
3142     {
3143         if (x.has_value()) {
3144             return 0;
3145         }
3146         return std::hash<E>{}(::RESULT_NS_IMPL::detail::extract_error(x));
3147     }
3148 };
3149 
3150 } // namespace std
3151 
3152 #if !defined(RESULT_DISABLE_EXCEPTIONS)
3153 
3154 //=============================================================================
3155 // class : bad_result_access
3156 //=============================================================================
3157 
3158 //-----------------------------------------------------------------------------
3159 // Constructors
3160 //-----------------------------------------------------------------------------
3161 
3162 template<typename E>
3163 template<typename E2, typename>
3164 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(E2&& error):
3165     logic_error{"error attempting to access value from result containing error"}, m_error(detail::forward<E2>(error))
3166 {
3167 }
3168 
3169 template<typename E>
3170 template<typename E2, typename>
3171 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(const char *what_arg,
3172                                                                                         E2&& error):
3173     logic_error{what_arg}, m_error(detail::forward<E2>(error))
3174 {
3175 }
3176 
3177 template<typename E>
3178 template<typename E2, typename>
3179 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(const std::string& what_arg,
3180                                                                                         E2&& error):
3181     logic_error{what_arg}, m_error(detail::forward<E2>(error))
3182 {
3183 }
3184 
3185 //-----------------------------------------------------------------------------
3186 // Observers
3187 //-----------------------------------------------------------------------------
3188 
3189 template<typename E>
3190 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::bad_result_access<E>::error() & noexcept -> E&
3191 {
3192     return m_error;
3193 }
3194 
3195 template<typename E>
3196 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::bad_result_access<E>::error() && noexcept -> E&&
3197 {
3198     return static_cast<E&&>(m_error);
3199 }
3200 
3201 template<typename E>
3202 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::bad_result_access<E>::error() const& noexcept -> const E&
3203 {
3204     return m_error;
3205 }
3206 
3207 template<typename E>
3208 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::bad_result_access<E>::error() const&& noexcept -> const E&&
3209 {
3210     return static_cast<const E&&>(m_error);
3211 }
3212 
3213 #endif
3214 
3215 //=============================================================================
3216 // class : failure
3217 //=============================================================================
3218 
3219 //-----------------------------------------------------------------------------
3220 // Constructors
3221 //-----------------------------------------------------------------------------
3222 
3223 template<typename E>
3224 template<typename... Args, typename>
3225 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::failure<E>::failure(in_place_t, Args&&...args) noexcept(
3226     std::is_nothrow_constructible<E, Args...>::value):
3227     m_failure(detail::forward<Args>(args)...)
3228 {
3229 }
3230 
3231 template<typename E>
3232 template<typename U, typename... Args, typename>
3233 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::failure<E>::failure(
3234     in_place_t,
3235     std::initializer_list<U> ilist,
3236     Args&&...args) noexcept(std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value):
3237     m_failure(ilist, detail::forward<Args>(args)...)
3238 {
3239 }
3240 
3241 template<typename E>
3242 template<
3243     typename E2,
3244     typename std::enable_if<RESULT_NS_IMPL::detail::failure_is_explicit_value_convertible<E, E2>::value, int>::type>
3245 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::failure<E>::failure(E2&& error) noexcept(
3246     std::is_nothrow_constructible<E, E2>::value):
3247     m_failure(detail::forward<E2>(error))
3248 {
3249 }
3250 
3251 template<typename E>
3252 template<
3253     typename E2,
3254     typename std::enable_if<RESULT_NS_IMPL::detail::failure_is_implicit_value_convertible<E, E2>::value, int>::type>
3255 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::failure<E>::failure(E2&& error) noexcept(
3256     std::is_nothrow_constructible<E, E2>::value):
3257     m_failure(detail::forward<E2>(error))
3258 {
3259 }
3260 
3261 template<typename E>
3262 template<typename E2, typename>
3263 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::failure<E>::failure(const failure<E2>& other) noexcept(
3264     std::is_nothrow_constructible<E, const E2&>::value):
3265     m_failure(other.error())
3266 {
3267 }
3268 
3269 template<typename E>
3270 template<typename E2, typename>
3271 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::failure<E>::failure(failure<E2>&& other) noexcept(
3272     std::is_nothrow_constructible<E, E2&&>::value):
3273     m_failure(static_cast<failure<E2>&&>(other).error())
3274 {
3275 }
3276 
3277 //-----------------------------------------------------------------------------
3278 
3279 template<typename E>
3280 template<typename E2, typename>
3281 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
3282 RESULT_NS_IMPL::failure<E>::operator=(E2&& error) noexcept(std::is_nothrow_assignable<E, E2>::value
3283                                                            || std::is_lvalue_reference<E>::value) -> failure&
3284 {
3285     m_failure = detail::forward<E2>(error);
3286 
3287     return (*this);
3288 }
3289 
3290 template<typename E>
3291 template<typename E2, typename>
3292 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::failure<E>::operator=(
3293     const failure<E2>& other) noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> failure&
3294 {
3295     m_failure = other.error();
3296 
3297     return (*this);
3298 }
3299 
3300 template<typename E>
3301 template<typename E2, typename>
3302 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
3303 RESULT_NS_IMPL::failure<E>::operator=(failure<E2>&& other) noexcept(std::is_nothrow_assignable<E, E2&&>::value)
3304     -> failure&
3305 {
3306     m_failure = static_cast<failure<E2>&&>(other).error();
3307 
3308     return (*this);
3309 }
3310 
3311 //-----------------------------------------------------------------------------
3312 // Observers
3313 //-----------------------------------------------------------------------------
3314 
3315 template<typename E>
3316 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::failure<E>::error() & noexcept ->
3317     typename std::add_lvalue_reference<E>::type
3318 {
3319     return m_failure;
3320 }
3321 
3322 template<typename E>
3323 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::failure<E>::error() && noexcept ->
3324     typename std::add_rvalue_reference<E>::type
3325 {
3326     using reference = typename std::add_rvalue_reference<E>::type;
3327 
3328     return static_cast<reference>(m_failure);
3329 }
3330 
3331 template<typename E>
3332 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::failure<E>::error() const& noexcept ->
3333     typename std::add_lvalue_reference<typename std::add_const<E>::type>::type
3334 {
3335     return m_failure;
3336 }
3337 
3338 template<typename E>
3339 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::failure<E>::error() const&& noexcept ->
3340     typename std::add_rvalue_reference<typename std::add_const<E>::type>::type
3341 {
3342     using reference = typename std::add_rvalue_reference<typename std::add_const<E>::type>::type;
3343 
3344     return static_cast<reference>(m_failure);
3345 }
3346 
3347 //=============================================================================
3348 // non-member functions : class : failure
3349 //=============================================================================
3350 
3351 //-----------------------------------------------------------------------------
3352 // Comparison
3353 //-----------------------------------------------------------------------------
3354 
3355 template<typename E1, typename E2>
3356 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator==(const failure<E1>& lhs,
3357                                                                           const failure<E2>& rhs) noexcept -> bool
3358 {
3359     return lhs.error() == rhs.error();
3360 }
3361 
3362 template<typename E1, typename E2>
3363 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator!=(const failure<E1>& lhs,
3364                                                                           const failure<E2>& rhs) noexcept -> bool
3365 {
3366     return lhs.error() != rhs.error();
3367 }
3368 
3369 template<typename E1, typename E2>
3370 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<(const failure<E1>& lhs,
3371                                                                          const failure<E2>& rhs) noexcept -> bool
3372 {
3373     return lhs.error() < rhs.error();
3374 }
3375 
3376 template<typename E1, typename E2>
3377 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>(const failure<E1>& lhs,
3378                                                                          const failure<E2>& rhs) noexcept -> bool
3379 {
3380     return lhs.error() > rhs.error();
3381 }
3382 
3383 template<typename E1, typename E2>
3384 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<=(const failure<E1>& lhs,
3385                                                                           const failure<E2>& rhs) noexcept -> bool
3386 {
3387     return lhs.error() <= rhs.error();
3388 }
3389 
3390 template<typename E1, typename E2>
3391 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>=(const failure<E1>& lhs,
3392                                                                           const failure<E2>& rhs) noexcept -> bool
3393 {
3394     return lhs.error() >= rhs.error();
3395 }
3396 
3397 //-----------------------------------------------------------------------------
3398 // Utilities
3399 //-----------------------------------------------------------------------------
3400 
3401 template<typename E>
3402 inline RESULT_INLINE_VISIBILITY constexpr auto
3403 RESULT_NS_IMPL::fail(E&& e) noexcept(std::is_nothrow_constructible<typename std::decay<E>::type, E>::value)
3404     -> failure<typename std::decay<E>::type>
3405 {
3406     using result_type = failure<typename std::decay<E>::type>;
3407 
3408     return result_type(detail::forward<E>(e));
3409 }
3410 
3411 template<typename E>
3412 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::fail(std::reference_wrapper<E> e) noexcept -> failure<E&>
3413 {
3414     using result_type = failure<E&>;
3415 
3416     return result_type{e.get()};
3417 }
3418 
3419 template<typename E, typename... Args, typename>
3420 inline RESULT_INLINE_VISIBILITY constexpr auto
3421 RESULT_NS_IMPL::fail(Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value) -> failure<E>
3422 {
3423     return failure<E>(in_place, detail::forward<Args>(args)...);
3424 }
3425 
3426 template<typename E, typename U, typename... Args, typename>
3427 inline RESULT_INLINE_VISIBILITY constexpr auto
3428 RESULT_NS_IMPL::fail(std::initializer_list<U> ilist,
3429                      Args&&...args) noexcept(std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value)
3430     -> failure<E>
3431 {
3432     return failure<E>(in_place, ilist, detail::forward<Args>(args)...);
3433 }
3434 
3435 template<typename E>
3436 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::swap(failure<E>& lhs, failure<E>& rhs)
3437 #if __cplusplus >= 201703L
3438     noexcept(std::is_nothrow_swappable<E>::value) -> void
3439 #else
3440     noexcept(std::is_nothrow_move_constructible<E>::value) -> void
3441 #endif
3442 {
3443     using std::swap;
3444 
3445     swap(lhs.error(), rhs.error());
3446 }
3447 
3448 //=============================================================================
3449 // class : detail::result_union<T, E, IsTrivial>
3450 //=============================================================================
3451 
3452 //-----------------------------------------------------------------------------
3453 // Constructors / Assignment
3454 //-----------------------------------------------------------------------------
3455 
3456 template<typename T, typename E, bool IsTrivial>
3457 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::result_union(unit) noexcept:
3458     m_empty{}
3459 {
3460     // m_has_value intentionally not set
3461 }
3462 
3463 template<typename T, typename E, bool IsTrivial>
3464 template<typename... Args>
3465 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::result_union(
3466     in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value):
3467     m_value(detail::forward<Args>(args)...), m_has_value{true}
3468 {
3469 }
3470 
3471 template<typename T, typename E, bool IsTrivial>
3472 template<typename... Args>
3473 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::result_union(
3474     in_place_error_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value):
3475     m_error(detail::forward<Args>(args)...), m_has_value{false}
3476 {
3477 }
3478 
3479 //-----------------------------------------------------------------------------
3480 // Modifiers
3481 //-----------------------------------------------------------------------------
3482 
3483 template<typename T, typename E, bool IsTrivial>
3484 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::destroy() const noexcept
3485     -> void
3486 {
3487     // do nothing
3488 }
3489 
3490 //=============================================================================
3491 // class : detail::result_union<T, E, false>
3492 //=============================================================================
3493 
3494 //-----------------------------------------------------------------------------
3495 // Constructors / Destructor / Assignment
3496 //-----------------------------------------------------------------------------
3497 
3498 template<typename T, typename E>
3499 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::detail::result_union<T, E, false>::result_union(unit) noexcept:
3500     m_empty{}
3501 {
3502     // m_has_value intentionally not set
3503 }
3504 
3505 template<typename T, typename E>
3506 template<typename... Args>
3507 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::detail::result_union<T, E, false>::result_union(
3508     in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value):
3509     m_value(detail::forward<Args>(args)...), m_has_value{true}
3510 {
3511 }
3512 
3513 template<typename T, typename E>
3514 template<typename... Args>
3515 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::detail::result_union<T, E, false>::result_union(
3516     in_place_error_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value):
3517     m_error(detail::forward<Args>(args)...), m_has_value{false}
3518 {
3519 }
3520 
3521 //-----------------------------------------------------------------------------
3522 
3523 #if __cplusplus >= 202002L
3524 template<typename T, typename E>
3525 inline RESULT_INLINE_VISIBILITY
3526     RESULT_NS_IMPL::detail::result_union<T, E, false>::result_union::~result_union() noexcept(
3527         std::is_nothrow_destructible<T>::value&& std::is_nothrow_destructible<E>::value)
3528 {
3529     destroy();
3530 }
3531 #else
3532 template<typename T, typename E>
3533 inline RESULT_INLINE_VISIBILITY
3534     RESULT_NS_IMPL::detail::result_union<T, E, false>::~result_union<T, E, false>() noexcept(
3535         std::is_nothrow_destructible<T>::value&& std::is_nothrow_destructible<E>::value)
3536 {
3537     destroy();
3538 }
3539 #endif
3540 
3541 //-----------------------------------------------------------------------------
3542 // Modifiers
3543 //-----------------------------------------------------------------------------
3544 
3545 template<typename T, typename E>
3546 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_union<T, E, false>::destroy() -> void
3547 {
3548     if (m_has_value) {
3549         m_value.~underlying_value_type();
3550     } else {
3551         m_error.~underlying_error_type();
3552     }
3553 }
3554 
3555 //=============================================================================
3556 // class : result_construct_base<T, E>
3557 //=============================================================================
3558 
3559 //-----------------------------------------------------------------------------
3560 // Constructors / Assignment
3561 //-----------------------------------------------------------------------------
3562 
3563 template<typename T, typename E>
3564 inline RESULT_INLINE_VISIBILITY
3565 RESULT_NS_IMPL::detail::result_construct_base<T, E>::result_construct_base(unit) noexcept:
3566     storage{unit{}}
3567 {
3568 }
3569 
3570 template<typename T, typename E>
3571 template<typename... Args>
3572 inline constexpr RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::detail::result_construct_base<T, E>::result_construct_base(
3573     in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value):
3574     storage{in_place, detail::forward<Args>(args)...}
3575 {
3576 }
3577 
3578 template<typename T, typename E>
3579 template<typename... Args>
3580 inline constexpr RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::detail::result_construct_base<T, E>::result_construct_base(
3581     in_place_error_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value):
3582     storage(in_place_error, detail::forward<Args>(args)...)
3583 {
3584 }
3585 
3586 //-----------------------------------------------------------------------------
3587 // Construction / Assignment
3588 //-----------------------------------------------------------------------------
3589 
3590 template<typename T, typename E>
3591 template<typename... Args>
3592 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_construct_base<T, E>::construct_value(
3593     Args&&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value) -> void
3594 {
3595     using value_type = typename storage_type::underlying_value_type;
3596 
3597     auto *p = static_cast<void *>(std::addressof(storage.m_value));
3598     new (p) value_type(detail::forward<Args>(args)...);
3599     storage.m_has_value = true;
3600 }
3601 
3602 template<typename T, typename E>
3603 template<typename... Args>
3604 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_construct_base<T, E>::construct_error(
3605     Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value) -> void
3606 {
3607     using error_type = typename storage_type::underlying_error_type;
3608 
3609     auto *p = static_cast<void *>(std::addressof(storage.m_error));
3610     new (p) error_type(detail::forward<Args>(args)...);
3611     storage.m_has_value = false;
3612 }
3613 
3614 template<typename T, typename E>
3615 template<typename Result>
3616 inline RESULT_INLINE_VISIBILITY auto
3617 RESULT_NS_IMPL::detail::result_construct_base<T, E>::construct_error_from_result(Result&& other) -> void
3618 {
3619     if (other.storage.m_has_value) {
3620         construct_value();
3621     } else {
3622         construct_error(detail::forward<Result>(other).storage.m_error);
3623     }
3624 }
3625 
3626 template<typename T, typename E>
3627 template<typename Result>
3628 inline RESULT_INLINE_VISIBILITY auto
3629 RESULT_NS_IMPL::detail::result_construct_base<T, E>::construct_from_result(Result&& other) -> void
3630 {
3631     if (other.storage.m_has_value) {
3632         construct_value_from_result_impl(std::is_lvalue_reference<T>{}, detail::forward<Result>(other).storage.m_value);
3633     } else {
3634         construct_error(detail::forward<Result>(other).storage.m_error);
3635     }
3636 }
3637 
3638 template<typename T, typename E>
3639 template<typename Value>
3640 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_construct_base<T, E>::assign_value(
3641     Value&& value) noexcept(std::is_nothrow_assignable<T, Value>::value) -> void
3642 {
3643     if (!storage.m_has_value) {
3644         storage.destroy();
3645         construct_value(detail::forward<Value>(value));
3646     } else {
3647         storage.m_value = detail::forward<Value>(value);
3648     }
3649 }
3650 
3651 template<typename T, typename E>
3652 template<typename Error>
3653 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_construct_base<T, E>::assign_error(
3654     Error&& error) noexcept(std::is_nothrow_assignable<E, Error>::value) -> void
3655 {
3656     if (storage.m_has_value) {
3657         storage.destroy();
3658         construct_error(detail::forward<Error>(error));
3659     } else {
3660         storage.m_error = detail::forward<Error>(error);
3661     }
3662 }
3663 
3664 template<typename T, typename E>
3665 template<typename Result>
3666 inline RESULT_INLINE_VISIBILITY auto
3667 RESULT_NS_IMPL::detail::result_construct_base<T, E>::assign_from_result(Result&& other) -> void
3668 {
3669     if (other.storage.m_has_value != storage.m_has_value) {
3670         storage.destroy();
3671         construct_from_result(detail::forward<Result>(other));
3672     } else if (storage.m_has_value) {
3673         assign_value_from_result_impl(std::is_lvalue_reference<T>{}, detail::forward<Result>(other));
3674     } else {
3675         storage.m_error = detail::forward<Result>(other).storage.m_error;
3676     }
3677 }
3678 
3679 template<typename T, typename E>
3680 template<typename ReferenceWrapper>
3681 inline RESULT_INLINE_VISIBILITY auto
3682 RESULT_NS_IMPL::detail::result_construct_base<T, E>::construct_value_from_result_impl(
3683     std::true_type, ReferenceWrapper&& reference) noexcept -> void
3684 {
3685     using value_type = typename storage_type::underlying_value_type;
3686 
3687     auto *p = static_cast<void *>(std::addressof(storage.m_value));
3688     new (p) value_type(reference.get());
3689     storage.m_has_value = true;
3690 }
3691 
3692 template<typename T, typename E>
3693 template<typename Value>
3694 inline RESULT_INLINE_VISIBILITY auto
3695 RESULT_NS_IMPL::detail::result_construct_base<T, E>::construct_value_from_result_impl(
3696     std::false_type, Value&& value) noexcept(std::is_nothrow_constructible<T, Value>::value) -> void
3697 {
3698     using value_type = typename storage_type::underlying_value_type;
3699 
3700     auto *p = static_cast<void *>(std::addressof(storage.m_value));
3701     new (p) value_type(detail::forward<Value>(value));
3702     storage.m_has_value = true;
3703 }
3704 
3705 template<typename T, typename E>
3706 template<typename Result>
3707 inline RESULT_INLINE_VISIBILITY auto
3708 RESULT_NS_IMPL::detail::result_construct_base<T, E>::assign_value_from_result_impl(std::true_type, Result&& other)
3709     -> void
3710 {
3711     // T is a reference; unwrap it
3712     storage.m_value = other.storage.m_value.get();
3713 }
3714 
3715 template<typename T, typename E>
3716 template<typename Result>
3717 inline RESULT_INLINE_VISIBILITY auto
3718 RESULT_NS_IMPL::detail::result_construct_base<T, E>::assign_value_from_result_impl(std::false_type, Result&& other)
3719     -> void
3720 {
3721     storage.m_value = detail::forward<Result>(other).storage.m_value;
3722 }
3723 
3724 //=============================================================================
3725 // class : result_trivial_copy_ctor_base_impl
3726 //=============================================================================
3727 
3728 template<typename T, typename E>
3729 inline RESULT_INLINE_VISIBILITY
3730 RESULT_NS_IMPL::detail::result_trivial_copy_ctor_base_impl<T, E>::result_trivial_copy_ctor_base_impl(
3731     const result_trivial_copy_ctor_base_impl&
3732         other) noexcept(std::is_nothrow_copy_constructible<T>::value&& std::is_nothrow_copy_constructible<E>::value):
3733     base_type(unit{})
3734 {
3735     using ctor_base = result_construct_base<T, E>;
3736 
3737     ctor_base::construct_from_result(static_cast<const ctor_base&>(other));
3738 }
3739 
3740 //=============================================================================
3741 // class : result_trivial_move_ctor_base
3742 //=============================================================================
3743 
3744 template<typename T, typename E>
3745 inline RESULT_INLINE_VISIBILITY
3746 RESULT_NS_IMPL::detail::result_trivial_move_ctor_base_impl<T, E>::result_trivial_move_ctor_base_impl(
3747     result_trivial_move_ctor_base_impl&&
3748         other) noexcept(std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_constructible<E>::value):
3749     base_type(unit{})
3750 {
3751     using ctor_base = result_construct_base<T, E>;
3752 
3753     ctor_base::construct_from_result(static_cast<ctor_base&&>(other));
3754 }
3755 
3756 //=============================================================================
3757 // class : result_copy_assign_base
3758 //=============================================================================
3759 
3760 template<typename T, typename E>
3761 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_trivial_copy_assign_base_impl<T, E>::operator=(
3762     const result_trivial_copy_assign_base_impl&
3763         other) noexcept(std::is_nothrow_copy_constructible<T>::value&& std::is_nothrow_copy_constructible<E>::value&&
3764                             std::is_nothrow_copy_assignable<T>::value&& std::is_nothrow_copy_assignable<E>::value)
3765     -> result_trivial_copy_assign_base_impl&
3766 {
3767     using ctor_base = result_construct_base<T, E>;
3768 
3769     ctor_base::assign_from_result(static_cast<const ctor_base&>(other));
3770     return (*this);
3771 }
3772 
3773 //=========================================================================
3774 // class : result_move_assign_base
3775 //=========================================================================
3776 
3777 template<typename T, typename E>
3778 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::result_trivial_move_assign_base_impl<T, E>::operator=(
3779     result_trivial_move_assign_base_impl&&
3780         other) noexcept(std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_constructible<E>::value&&
3781                             std::is_nothrow_move_assignable<T>::value&& std::is_nothrow_move_assignable<E>::value)
3782     -> result_trivial_move_assign_base_impl&
3783 {
3784     using ctor_base = result_construct_base<T, E>;
3785 
3786     ctor_base::assign_from_result(static_cast<ctor_base&&>(other));
3787     return (*this);
3788 }
3789 
3790 template<typename T, typename E>
3791 inline RESULT_INLINE_VISIBILITY constexpr auto
3792 RESULT_NS_IMPL::detail::result_error_extractor::get(const result<T, E>& exp) noexcept -> const E&
3793 {
3794     return exp.m_storage.storage.m_error;
3795 }
3796 
3797 template<typename T, typename E>
3798 inline RESULT_INLINE_VISIBILITY constexpr auto
3799 RESULT_NS_IMPL::detail::result_error_extractor::get(result<T, E>& exp) noexcept -> E&
3800 {
3801     return exp.m_storage.storage.m_error;
3802 }
3803 
3804 template<typename T, typename E>
3805 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::detail::extract_error(const result<T, E>& exp) noexcept
3806     -> const E&
3807 {
3808     return result_error_extractor::get(exp);
3809 }
3810 
3811 template<typename E>
3812 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::throw_bad_result_access(E&& error) -> void
3813 {
3814 #if defined(RESULT_DISABLE_EXCEPTIONS)
3815     std::fprintf(stderr, "error attempting to access value from result containing error\n");
3816     std::abort();
3817 #else
3818     using exception_type = bad_result_access<typename std::remove_const<typename std::remove_reference<E>::type>::type>;
3819 
3820     throw exception_type{detail::forward<E>(error)};
3821 #endif
3822 }
3823 
3824 template<typename String, typename E>
3825 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::detail::throw_bad_result_access_message(String&& message,
3826                                                                                              E&& error) -> void
3827 {
3828 #if defined(RESULT_DISABLE_EXCEPTIONS)
3829     const auto message_string = std::string{detail::forward<String>(message)};
3830     std::fprintf(stderr, "%s\n", message_string.c_str());
3831     std::abort();
3832 #else
3833     using exception_type = bad_result_access<typename std::remove_const<typename std::remove_reference<E>::type>::type>;
3834 
3835     throw exception_type{detail::forward<String>(message), detail::forward<E>(error)};
3836 #endif
3837 }
3838 
3839 //=============================================================================
3840 // class : result<T,E>
3841 //=============================================================================
3842 
3843 template<typename T, typename E>
3844 template<typename U, typename>
3845 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result() noexcept(
3846     std::is_nothrow_constructible<U>::value):
3847     m_storage(in_place)
3848 {
3849 }
3850 
3851 template<typename T, typename E>
3852 template<typename T2,
3853          typename E2,
3854          typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_copy_convertible<T, E, T2, E2>::value,
3855                                  int>::type>
3856 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::result<T, E>::result(const result<T2, E2>& other) noexcept(
3857     std::is_nothrow_constructible<T, const T2&>::value&& std::is_nothrow_constructible<E, const E2&>::value):
3858     m_storage(detail::unit{})
3859 {
3860     m_storage.construct_from_result(static_cast<const result<T2, E2>&>(other).m_storage);
3861 }
3862 
3863 template<typename T, typename E>
3864 template<typename T2,
3865          typename E2,
3866          typename std::enable_if<RESULT_NS_IMPL::detail::result_is_explicit_copy_convertible<T, E, T2, E2>::value,
3867                                  int>::type>
3868 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::result<T, E>::result(const result<T2, E2>& other) noexcept(
3869     std::is_nothrow_constructible<T, const T2&>::value&& std::is_nothrow_constructible<E, const E2&>::value):
3870     m_storage(detail::unit{})
3871 {
3872     m_storage.construct_from_result(static_cast<const result<T2, E2>&>(other).m_storage);
3873 }
3874 
3875 template<typename T, typename E>
3876 template<typename T2,
3877          typename E2,
3878          typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_move_convertible<T, E, T2, E2>::value,
3879                                  int>::type>
3880 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::result<T, E>::result(result<T2, E2>&& other) noexcept(
3881     std::is_nothrow_constructible<T, T2&&>::value&& std::is_nothrow_constructible<E, E2&&>::value):
3882     m_storage(detail::unit{})
3883 {
3884     m_storage.construct_from_result(static_cast<result<T2, E2>&&>(other).m_storage);
3885 }
3886 
3887 template<typename T, typename E>
3888 template<typename T2,
3889          typename E2,
3890          typename std::enable_if<RESULT_NS_IMPL::detail::result_is_explicit_move_convertible<T, E, T2, E2>::value,
3891                                  int>::type>
3892 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::result<T, E>::result(result<T2, E2>&& other) noexcept(
3893     std::is_nothrow_constructible<T, T2&&>::value&& std::is_nothrow_constructible<E, E2&&>::value):
3894     m_storage(detail::unit{})
3895 {
3896     m_storage.construct_from_result(static_cast<result<T2, E2>&&>(other).m_storage);
3897 }
3898 
3899 //-----------------------------------------------------------------------------
3900 
3901 template<typename T, typename E>
3902 template<typename... Args, typename>
3903 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(in_place_t, Args&&...args) noexcept(
3904     std::is_nothrow_constructible<T, Args...>::value):
3905     m_storage(in_place, detail::forward<Args>(args)...)
3906 {
3907 }
3908 
3909 template<typename T, typename E>
3910 template<typename U, typename... Args, typename>
3911 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(
3912     in_place_t,
3913     std::initializer_list<U> ilist,
3914     Args&&...args) noexcept(std::is_nothrow_constructible<T, std::initializer_list<U>, Args...>::value):
3915     m_storage(in_place, ilist, detail::forward<Args>(args)...)
3916 {
3917 }
3918 
3919 //-----------------------------------------------------------------------------
3920 
3921 template<typename T, typename E>
3922 template<typename... Args, typename>
3923 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(
3924     in_place_error_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value):
3925     m_storage(in_place_error, detail::forward<Args>(args)...)
3926 {
3927 }
3928 
3929 template<typename T, typename E>
3930 template<typename U, typename... Args, typename>
3931 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(
3932     in_place_error_t,
3933     std::initializer_list<U> ilist,
3934     Args&&...args) noexcept(std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value):
3935     m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
3936 {
3937 }
3938 
3939 //-------------------------------------------------------------------------
3940 
3941 template<typename T, typename E>
3942 template<typename E2, typename>
3943 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(const failure<E2>& e) noexcept(
3944     std::is_nothrow_constructible<E, const E2&>::value):
3945     m_storage(in_place_error, e.error())
3946 {
3947 }
3948 
3949 template<typename T, typename E>
3950 template<typename E2, typename>
3951 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(failure<E2>&& e) noexcept(
3952     std::is_nothrow_constructible<E, E2&&>::value):
3953     m_storage(in_place_error, static_cast<E2&&>(e.error()))
3954 {
3955 }
3956 
3957 template<typename T, typename E>
3958 template<typename U,
3959          typename std::enable_if<RESULT_NS_IMPL::detail::result_is_explicit_value_convertible<T, U>::value, int>::type>
3960 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(U&& value) noexcept(
3961     std::is_nothrow_constructible<T, U>::value):
3962     m_storage(in_place, detail::forward<U>(value))
3963 {
3964 }
3965 
3966 template<typename T, typename E>
3967 template<typename U,
3968          typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_value_convertible<T, U>::value, int>::type>
3969 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::result(U&& value) noexcept(
3970     std::is_nothrow_constructible<T, U>::value):
3971     m_storage(in_place, detail::forward<U>(value))
3972 {
3973 }
3974 
3975 //-----------------------------------------------------------------------------
3976 
3977 template<typename T, typename E>
3978 template<typename T2, typename E2, typename>
3979 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::result<T, E>::operator=(const result<T2, E2>& other) noexcept(
3980     std::is_nothrow_assignable<T, const T2&>::value&& std::is_nothrow_assignable<E, const E2&>::value) -> result&
3981 {
3982     m_storage.assign_from_result(static_cast<const result<T2, E2>&>(other).m_storage);
3983     return (*this);
3984 }
3985 
3986 template<typename T, typename E>
3987 template<typename T2, typename E2, typename>
3988 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::result<T, E>::operator=(result<T2, E2>&& other) noexcept(
3989     std::is_nothrow_assignable<T, T2&&>::value&& std::is_nothrow_assignable<E, E2&&>::value) -> result&
3990 {
3991     m_storage.assign_from_result(static_cast<result<T2, E2>&&>(other).m_storage);
3992     return (*this);
3993 }
3994 
3995 template<typename T, typename E>
3996 template<typename U, typename>
3997 inline RESULT_INLINE_VISIBILITY auto
3998 RESULT_NS_IMPL::result<T, E>::operator=(U&& value) noexcept(std::is_nothrow_assignable<T, U>::value) -> result&
3999 {
4000     m_storage.assign_value(detail::forward<U>(value));
4001     return (*this);
4002 }
4003 
4004 template<typename T, typename E>
4005 template<typename E2, typename>
4006 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::result<T, E>::operator=(const failure<E2>& other) noexcept(
4007     std::is_nothrow_assignable<E, const E2&>::value) -> result&
4008 {
4009     m_storage.assign_error(other.error());
4010     return (*this);
4011 }
4012 
4013 template<typename T, typename E>
4014 template<typename E2, typename>
4015 inline RESULT_INLINE_VISIBILITY auto
4016 RESULT_NS_IMPL::result<T, E>::operator=(failure<E2>&& other) noexcept(std::is_nothrow_assignable<E, E2&&>::value)
4017     -> result&
4018 {
4019     m_storage.assign_error(static_cast<E2&&>(other.error()));
4020     return (*this);
4021 }
4022 
4023 //-----------------------------------------------------------------------------
4024 // Observers
4025 //-----------------------------------------------------------------------------
4026 
4027 template<typename T, typename E>
4028 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::operator->() noexcept ->
4029     typename std::remove_reference<T>::type *
4030 {
4031     // Prior to C++17, std::addressof was not `constexpr`.
4032     // Since `addressof` fixes a relatively obscure issue where users define a
4033     // custom `operator&`, the pre-C++17 implementation has been defined to be
4034     // `&(**this)` so that it may exist in constexpr contexts.
4035 #if __cplusplus >= 201703L
4036     return std::addressof(**this);
4037 #else
4038     return &(**this);
4039 #endif
4040 }
4041 
4042 template<typename T, typename E>
4043 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::operator->() const noexcept ->
4044     typename std::remove_reference<typename std::add_const<T>::type>::type *
4045 {
4046 #if __cplusplus >= 201703L
4047     return std::addressof(**this);
4048 #else
4049     return &(**this);
4050 #endif
4051 }
4052 
4053 template<typename T, typename E>
4054 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::operator*() & noexcept ->
4055     typename std::add_lvalue_reference<T>::type
4056 {
4057     return m_storage.storage.m_value;
4058 }
4059 
4060 template<typename T, typename E>
4061 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::operator*() && noexcept ->
4062     typename std::add_rvalue_reference<T>::type
4063 {
4064     using reference = typename std::add_rvalue_reference<T>::type;
4065 
4066     return static_cast<reference>(m_storage.storage.m_value);
4067 }
4068 
4069 template<typename T, typename E>
4070 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::operator*() const& noexcept ->
4071     typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
4072 {
4073     return m_storage.storage.m_value;
4074 }
4075 
4076 template<typename T, typename E>
4077 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::operator*() const&& noexcept ->
4078     typename std::add_rvalue_reference<typename std::add_const<T>::type>::type
4079 {
4080     using reference = typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
4081 
4082     return static_cast<reference>(m_storage.storage.m_value);
4083 }
4084 
4085 //-----------------------------------------------------------------------------
4086 
4087 template<typename T, typename E>
4088 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<T, E>::operator bool() const noexcept
4089 {
4090     return m_storage.storage.m_has_value;
4091 }
4092 
4093 template<typename T, typename E>
4094 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::has_value() const noexcept -> bool
4095 {
4096     return m_storage.storage.m_has_value;
4097 }
4098 
4099 template<typename T, typename E>
4100 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::has_error() const noexcept -> bool
4101 {
4102     return !m_storage.storage.m_has_value;
4103 }
4104 
4105 //-----------------------------------------------------------------------------
4106 
4107 // The `has_value()` expression below is incorrectly identified as an unused
4108 // value, which results in the `-Wunused-value` warning. This is suppressed
4109 // to prevent false-positives
4110 #if defined(__clang__)
4111 #pragma clang diagnostic push
4112 #pragma clang diagnostic ignored "-Wunused-value"
4113 #elif defined(__GNUC__)
4114 #pragma GCC diagnostic push
4115 #pragma GCC diagnostic ignored "-Wunused-value"
4116 #elif defined(_MSC_VER)
4117 // Older MSVC versions incorrectly warn on returning a reference to a temporary.
4118 // This has been suppressed
4119 #pragma warning(push)
4120 #pragma warning(disable : 4172)
4121 #endif
4122 
4123 template<typename T, typename E>
4124 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::value() & ->
4125     typename std::add_lvalue_reference<T>::type
4126 {
4127     return (has_value() || (detail::throw_bad_result_access(m_storage.storage.m_error), false),
4128             m_storage.storage.m_value);
4129 }
4130 
4131 template<typename T, typename E>
4132 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::value() && ->
4133     typename std::add_rvalue_reference<T>::type
4134 {
4135     using reference = typename std::add_rvalue_reference<T>::type;
4136 
4137     return (has_value() || (detail::throw_bad_result_access(static_cast<E&&>(m_storage.storage.m_error)), true),
4138             static_cast<reference>(m_storage.storage.m_value));
4139 }
4140 
4141 template<typename T, typename E>
4142 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::value() const& ->
4143     typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
4144 {
4145     return (has_value() || (detail::throw_bad_result_access(m_storage.storage.m_error), true),
4146             m_storage.storage.m_value);
4147 }
4148 
4149 template<typename T, typename E>
4150 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::value() const&& ->
4151     typename std::add_rvalue_reference<typename std::add_const<T>::type>::type
4152 {
4153     using reference = typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
4154 
4155     return (has_value() || (detail::throw_bad_result_access(static_cast<const E&&>(m_storage.storage.m_error)), true),
4156             (static_cast<reference>(m_storage.storage.m_value)));
4157 }
4158 
4159 #if defined(__clang__)
4160 #pragma clang diagnostic pop
4161 #elif defined(__GNUC__)
4162 #pragma GCC diagnostic pop
4163 #elif defined(_MSC_VER)
4164 #pragma warning(pop)
4165 #endif
4166 
4167 template<typename T, typename E>
4168 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::error() const& noexcept(
4169     std::is_nothrow_constructible<E>::value&& std::is_nothrow_copy_constructible<E>::value) -> E
4170 {
4171     static_assert(std::is_default_constructible<E>::value,
4172                   "E must be default-constructible if 'error()' checks are used. "
4173                   "This is to allow for default-constructed error states to represent the "
4174                   "'good' state");
4175 
4176     return m_storage.storage.m_has_value ? E{} : m_storage.storage.m_error;
4177 }
4178 
4179 template<typename T, typename E>
4180 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::error() && noexcept(
4181     std::is_nothrow_constructible<E>::value&& std::is_nothrow_move_constructible<E>::value) -> E
4182 {
4183     static_assert(std::is_default_constructible<E>::value,
4184                   "E must be default-constructible if 'error()' checks are used. "
4185                   "This is to allow for default-constructed error states to represent the "
4186                   "'good' state");
4187 
4188     return m_storage.storage.m_has_value ? E{} : static_cast<E&&>(m_storage.storage.m_error);
4189 }
4190 
4191 //-----------------------------------------------------------------------------
4192 
4193 template<typename T, typename E>
4194 template<typename String, typename>
4195 inline RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::expect(String&& message) const& -> void
4196 {
4197     if (has_error()) {
4198         detail::throw_bad_result_access_message(detail::forward<String>(message), m_storage.storage.m_error);
4199     }
4200 }
4201 
4202 template<typename T, typename E>
4203 template<typename String, typename>
4204 inline RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<T, E>::expect(String&& message) && -> void
4205 {
4206     if (has_error()) {
4207         detail::throw_bad_result_access_message(detail::forward<String>(message),
4208                                                 static_cast<E&&>(m_storage.storage.m_error));
4209     }
4210 }
4211 
4212 //-----------------------------------------------------------------------------
4213 // Monadic Functionalities
4214 //-----------------------------------------------------------------------------
4215 
4216 template<typename T, typename E>
4217 template<typename U>
4218 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::value_or(U&& default_value) const& ->
4219     typename std::remove_reference<T>::type
4220 {
4221     return m_storage.storage.m_has_value ? m_storage.storage.m_value : detail::forward<U>(default_value);
4222 }
4223 
4224 template<typename T, typename E>
4225 template<typename U>
4226 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4227 RESULT_NS_IMPL::result<T, E>::value_or(U&& default_value) && -> typename std::remove_reference<T>::type
4228 {
4229     return m_storage.storage.m_has_value ? static_cast<T&&>(**this) : detail::forward<U>(default_value);
4230 }
4231 
4232 template<typename T, typename E>
4233 template<typename U>
4234 inline RESULT_INLINE_VISIBILITY constexpr auto
4235 RESULT_NS_IMPL::result<T, E>::error_or(U&& default_error) const& -> error_type
4236 {
4237     return m_storage.storage.m_has_value ? detail::forward<U>(default_error) : m_storage.storage.m_error;
4238 }
4239 
4240 template<typename T, typename E>
4241 template<typename U>
4242 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4243 RESULT_NS_IMPL::result<T, E>::error_or(U&& default_error) && -> error_type
4244 {
4245     return m_storage.storage.m_has_value ? detail::forward<U>(default_error)
4246                                          : static_cast<E&&>(m_storage.storage.m_error);
4247 }
4248 
4249 template<typename T, typename E>
4250 template<typename U>
4251 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::and_then(U&& value) const
4252     -> result<typename std::decay<U>::type, E>
4253 {
4254     return map([&value](const T&) {
4255         return detail::forward<U>(value);
4256     });
4257 }
4258 
4259 //-----------------------------------------------------------------------------
4260 
4261 template<typename T, typename E>
4262 template<typename Fn>
4263 inline RESULT_INLINE_VISIBILITY constexpr auto
4264 RESULT_NS_IMPL::result<T, E>::flat_map(Fn&& fn) const& -> detail::invoke_result_t<Fn, const T&>
4265 {
4266     using result_type = detail::invoke_result_t<Fn, const T&>;
4267 
4268     static_assert(is_result<result_type>::value, "flat_map must return a result type or the program is ill-formed");
4269 
4270     return has_value() ? detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value)
4271                        : result_type(in_place_error, m_storage.storage.m_error);
4272 }
4273 
4274 template<typename T, typename E>
4275 template<typename Fn>
4276 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4277 RESULT_NS_IMPL::result<T, E>::flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn, T&&>
4278 {
4279     using result_type = detail::invoke_result_t<Fn, T&&>;
4280 
4281     static_assert(is_result<result_type>::value, "flat_map must return a result type or the program is ill-formed");
4282 
4283     return has_value() ? detail::invoke(detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value))
4284                        : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4285 }
4286 
4287 template<typename T, typename E>
4288 template<typename Fn>
4289 inline RESULT_INLINE_VISIBILITY constexpr auto
4290 RESULT_NS_IMPL::result<T, E>::map(Fn&& fn) const& -> result<detail::invoke_result_t<Fn, const T&>, E>
4291 {
4292     using result_type = detail::invoke_result_t<Fn, const T&>;
4293 
4294     return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4295 }
4296 
4297 template<typename T, typename E>
4298 template<typename Fn>
4299 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4300 RESULT_NS_IMPL::result<T, E>::map(Fn&& fn) && -> result<detail::invoke_result_t<Fn, T&&>, E>
4301 {
4302     using result_type = detail::invoke_result_t<Fn, T&&>;
4303 
4304     return static_cast<result<T, E>&&>(*this).map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4305 }
4306 
4307 //-----------------------------------------------------------------------------
4308 
4309 template<typename T, typename E>
4310 template<typename Fn>
4311 inline RESULT_INLINE_VISIBILITY constexpr auto
4312 RESULT_NS_IMPL::result<T, E>::map_error(Fn&& fn) const& -> result<T, detail::invoke_result_t<Fn, const E&>>
4313 {
4314     using result_type = result<T, detail::invoke_result_t<Fn, const E&>>;
4315 
4316     return has_error() ? result_type(in_place_error, detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error))
4317                        : result_type(in_place, m_storage.storage.m_value);
4318 }
4319 
4320 template<typename T, typename E>
4321 template<typename Fn>
4322 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4323 RESULT_NS_IMPL::result<T, E>::map_error(Fn&& fn) && -> result<T, detail::invoke_result_t<Fn, E&&>>
4324 {
4325     using result_type = result<T, detail::invoke_result_t<Fn, E&&>>;
4326 
4327     return has_error()
4328         ? result_type(in_place_error,
4329                       detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error)))
4330         : result_type(static_cast<T&&>(m_storage.storage.m_value));
4331 }
4332 
4333 template<typename T, typename E>
4334 template<typename Fn>
4335 inline RESULT_INLINE_VISIBILITY constexpr auto
4336 RESULT_NS_IMPL::result<T, E>::flat_map_error(Fn&& fn) const& -> detail::invoke_result_t<Fn, const E&>
4337 {
4338     using result_type = detail::invoke_result_t<Fn, const E&>;
4339 
4340     static_assert(is_result<result_type>::value,
4341                   "flat_map_error must return a result type or the program is ill-formed");
4342 
4343     return has_value() ? result_type(in_place, m_storage.storage.m_value)
4344                        : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
4345 }
4346 
4347 template<typename T, typename E>
4348 template<typename Fn>
4349 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4350 RESULT_NS_IMPL::result<T, E>::flat_map_error(Fn&& fn) && -> detail::invoke_result_t<Fn, E&&>
4351 {
4352     using result_type = detail::invoke_result_t<Fn, E&&>;
4353 
4354     static_assert(is_result<result_type>::value,
4355                   "flat_map_error must return a result type or the program is ill-formed");
4356 
4357     return has_value() ? result_type(in_place, static_cast<T&&>(m_storage.storage.m_value))
4358                        : detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error));
4359 }
4360 
4361 //-----------------------------------------------------------------------------
4362 // Private Monadic Functions
4363 //-----------------------------------------------------------------------------
4364 
4365 template<typename T, typename E>
4366 template<typename Fn>
4367 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type,
4368                                                                                       Fn&& fn) const& -> result<void, E>
4369 {
4370     using result_type = result<void, E>;
4371 
4372     return has_value() ? (detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value), result_type{})
4373                        : result_type(in_place_error, m_storage.storage.m_error);
4374 }
4375 
4376 template<typename T, typename E>
4377 template<typename Fn>
4378 inline RESULT_INLINE_VISIBILITY constexpr auto
4379 RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type,
4380                                        Fn&& fn) const& -> result<detail::invoke_result_t<Fn, const T&>, E>
4381 {
4382     using invoke_result_type = detail::invoke_result_t<Fn, const T&>;
4383     using result_type = result<invoke_result_type, E>;
4384 
4385     return has_value() ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value))
4386                        : result_type(in_place_error, m_storage.storage.m_error);
4387 }
4388 
4389 template<typename T, typename E>
4390 template<typename Fn>
4391 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4392 RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn) && -> result<void, E>
4393 {
4394     using result_type = result<void, E>;
4395 
4396     return has_value()
4397         ? (detail::invoke(detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value)), result_type{})
4398         : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4399 }
4400 
4401 template<typename T, typename E>
4402 template<typename Fn>
4403 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4404 RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn, T&&>, E>
4405 {
4406     using invoke_result_type = detail::invoke_result_t<Fn, T&&>;
4407     using result_type = result<invoke_result_type, E>;
4408 
4409     return has_value()
4410         ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value)))
4411         : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4412 }
4413 
4414 //=============================================================================
4415 // class : result<void,E>
4416 //=============================================================================
4417 
4418 //-----------------------------------------------------------------------------
4419 // Constructor / Assignment
4420 //-----------------------------------------------------------------------------
4421 
4422 template<typename E>
4423 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<void, E>::result() noexcept: m_storage(in_place)
4424 {
4425 }
4426 
4427 template<typename E>
4428 template<typename U, typename E2, typename>
4429 inline RESULT_INLINE_VISIBILITY RESULT_NS_IMPL::result<void, E>::result(const result<U, E2>& other) noexcept(
4430     std::is_nothrow_constructible<E, const E2&>::value):
4431     m_storage(detail::unit{})
4432 {
4433     m_storage.construct_error_from_result(static_cast<const result<U, E2>&>(other).m_storage);
4434 }
4435 
4436 template<typename E>
4437 template<typename U, typename E2, typename>
4438 inline RESULT_INLINE_VISIBILITY
4439 RESULT_NS_IMPL::result<void, E>::result(result<U, E2>&& other) noexcept(std::is_nothrow_constructible<E, E2&&>::value):
4440     m_storage(detail::unit{})
4441 {
4442     m_storage.construct_error_from_result(static_cast<result<U, E2>&&>(other).m_storage);
4443 }
4444 
4445 //-----------------------------------------------------------------------------
4446 
4447 template<typename E>
4448 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<void, E>::result(in_place_t) noexcept:
4449     m_storage(in_place)
4450 {
4451 }
4452 
4453 template<typename E>
4454 template<typename... Args, typename>
4455 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<void, E>::result(
4456     in_place_error_t, Args&&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value):
4457     m_storage(in_place_error, detail::forward<Args>(args)...)
4458 {
4459 }
4460 
4461 template<typename E>
4462 template<typename U, typename... Args, typename>
4463 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<void, E>::result(
4464     in_place_error_t,
4465     std::initializer_list<U> ilist,
4466     Args&&...args) noexcept(std::is_nothrow_constructible<E, std::initializer_list<U>, Args...>::value):
4467     m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
4468 {
4469 }
4470 
4471 //-----------------------------------------------------------------------------
4472 
4473 template<typename E>
4474 template<typename E2, typename>
4475 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<void, E>::result(const failure<E2>& e) noexcept(
4476     std::is_nothrow_constructible<E, const E2&>::value):
4477     m_storage(in_place_error, e.error())
4478 {
4479 }
4480 
4481 template<typename E>
4482 template<typename E2, typename>
4483 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<void, E>::result(failure<E2>&& e) noexcept(
4484     std::is_nothrow_constructible<E, E2&&>::value):
4485     m_storage(in_place_error, static_cast<E2&&>(e.error()))
4486 {
4487 }
4488 
4489 //-----------------------------------------------------------------------------
4490 
4491 template<typename E>
4492 template<typename E2, typename>
4493 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::result<void, E>::operator=(const result<void, E2>& other) noexcept(
4494     std::is_nothrow_assignable<E, const E2&>::value) -> result&
4495 {
4496     m_storage.assign_from_result(other.m_storage);
4497     return (*this);
4498 }
4499 
4500 template<typename E>
4501 template<typename E2, typename>
4502 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::result<void, E>::operator=(result<void, E2>&& other) noexcept(
4503     std::is_nothrow_assignable<E, E2&&>::value) -> result&
4504 {
4505     m_storage.assign_from_result(static_cast<result<void, E2>&&>(other).m_storage);
4506     return (*this);
4507 }
4508 
4509 template<typename E>
4510 template<typename E2, typename>
4511 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::result<void, E>::operator=(const failure<E2>& other) noexcept(
4512     std::is_nothrow_assignable<E, const E2&>::value) -> result&
4513 {
4514     m_storage.assign_error(other.error());
4515     return (*this);
4516 }
4517 
4518 template<typename E>
4519 template<typename E2, typename>
4520 inline RESULT_INLINE_VISIBILITY auto
4521 RESULT_NS_IMPL::result<void, E>::operator=(failure<E2>&& other) noexcept(std::is_nothrow_assignable<E, E2&&>::value)
4522     -> result&
4523 {
4524     m_storage.assign_error(static_cast<E2&&>(other.error()));
4525     return (*this);
4526 }
4527 
4528 //-----------------------------------------------------------------------------
4529 // Observers
4530 //-----------------------------------------------------------------------------
4531 
4532 template<typename E>
4533 inline RESULT_INLINE_VISIBILITY constexpr RESULT_NS_IMPL::result<void, E>::operator bool() const noexcept
4534 {
4535     return has_value();
4536 }
4537 
4538 template<typename E>
4539 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<void, E>::has_value() const noexcept -> bool
4540 {
4541     return m_storage.storage.m_has_value;
4542 }
4543 
4544 template<typename E>
4545 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<void, E>::has_error() const noexcept -> bool
4546 {
4547     return !has_value();
4548 }
4549 
4550 //-----------------------------------------------------------------------------
4551 
4552 template<typename E>
4553 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<void, E>::value() const& -> void
4554 {
4555     static_cast<void>(has_value() || (detail::throw_bad_result_access(m_storage.storage.m_error), true));
4556 }
4557 
4558 template<typename E>
4559 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<void, E>::value() && -> void
4560 {
4561     static_cast<void>(has_value()
4562                       || (detail::throw_bad_result_access(static_cast<E&&>(m_storage.storage.m_error)), true));
4563 }
4564 
4565 template<typename E>
4566 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<void, E>::error() const& noexcept(
4567     std::is_nothrow_constructible<E>::value&& std::is_nothrow_copy_constructible<E>::value) -> E
4568 {
4569     return has_value() ? E{} : m_storage.storage.m_error;
4570 }
4571 
4572 template<typename E>
4573 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<void, E>::error() && noexcept(
4574     std::is_nothrow_constructible<E>::value&& std::is_nothrow_copy_constructible<E>::value) -> E
4575 {
4576     return has_value() ? E{} : static_cast<E&&>(m_storage.storage.m_error);
4577 }
4578 
4579 //-----------------------------------------------------------------------------
4580 
4581 template<typename E>
4582 template<typename String, typename>
4583 inline RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<void, E>::expect(String&& message) const& -> void
4584 {
4585     if (has_error()) {
4586         detail::throw_bad_result_access_message(detail::forward<String>(message), m_storage.storage.m_error);
4587     }
4588 }
4589 
4590 template<typename E>
4591 template<typename String, typename>
4592 inline RESULT_CPP14_CONSTEXPR auto RESULT_NS_IMPL::result<void, E>::expect(String&& message) && -> void
4593 {
4594     if (has_error()) {
4595         detail::throw_bad_result_access_message(detail::forward<String>(message),
4596                                                 static_cast<E&&>(m_storage.storage.m_error));
4597     }
4598 }
4599 
4600 //-----------------------------------------------------------------------------
4601 // Monadic Functionalities
4602 //-----------------------------------------------------------------------------
4603 
4604 template<typename E>
4605 template<typename U>
4606 inline RESULT_INLINE_VISIBILITY constexpr auto
4607 RESULT_NS_IMPL::result<void, E>::error_or(U&& default_error) const& -> error_type
4608 {
4609     return has_value() ? detail::forward<U>(default_error) : m_storage.storage.m_error;
4610 }
4611 
4612 template<typename E>
4613 template<typename U>
4614 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4615 RESULT_NS_IMPL::result<void, E>::error_or(U&& default_error) && -> error_type
4616 {
4617     return has_value() ? detail::forward<U>(default_error) : static_cast<E&&>(m_storage.storage.m_error);
4618 }
4619 
4620 template<typename E>
4621 template<typename U>
4622 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::result<void, E>::and_then(U&& value) const
4623     -> result<typename std::decay<U>::type, E>
4624 {
4625     return map([&value] {
4626         return detail::forward<U>(value);
4627     });
4628 }
4629 
4630 //-----------------------------------------------------------------------------
4631 
4632 template<typename E>
4633 template<typename Fn>
4634 inline RESULT_INLINE_VISIBILITY constexpr auto
4635 RESULT_NS_IMPL::result<void, E>::flat_map(Fn&& fn) const& -> detail::invoke_result_t<Fn>
4636 {
4637     using result_type = detail::invoke_result_t<Fn>;
4638 
4639     static_assert(is_result<result_type>::value, "flat_map must return a result type or the program is ill-formed");
4640 
4641     return has_value() ? detail::invoke(detail::forward<Fn>(fn))
4642                        : result_type(in_place_error, m_storage.storage.m_error);
4643 }
4644 
4645 template<typename E>
4646 template<typename Fn>
4647 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4648 RESULT_NS_IMPL::result<void, E>::flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn>
4649 {
4650     using result_type = detail::invoke_result_t<Fn>;
4651 
4652     static_assert(is_result<result_type>::value, "flat_map must return a result type or the program is ill-formed");
4653 
4654     return has_value() ? detail::invoke(detail::forward<Fn>(fn))
4655                        : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4656 }
4657 
4658 template<typename E>
4659 template<typename Fn>
4660 inline RESULT_INLINE_VISIBILITY constexpr auto
4661 RESULT_NS_IMPL::result<void, E>::map(Fn&& fn) const& -> result<detail::invoke_result_t<Fn>, E>
4662 {
4663     using result_type = detail::invoke_result_t<Fn>;
4664 
4665     return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4666 }
4667 
4668 template<typename E>
4669 template<typename Fn>
4670 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4671 RESULT_NS_IMPL::result<void, E>::map(Fn&& fn) && -> result<detail::invoke_result_t<Fn>, E>
4672 {
4673     using result_type = detail::invoke_result_t<Fn>;
4674 
4675     return static_cast<result<void, E>&&>(*this).map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4676 }
4677 
4678 //-----------------------------------------------------------------------------
4679 
4680 template<typename E>
4681 template<typename Fn>
4682 inline RESULT_INLINE_VISIBILITY constexpr auto
4683 RESULT_NS_IMPL::result<void, E>::map_error(Fn&& fn) const& -> result<void, detail::invoke_result_t<Fn, const E&>>
4684 {
4685     using result_type = result<void, detail::invoke_result_t<Fn, const E&>>;
4686 
4687     return has_value()
4688         ? result_type{}
4689         : result_type(in_place_error, detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error));
4690 }
4691 
4692 template<typename E>
4693 template<typename Fn>
4694 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4695 RESULT_NS_IMPL::result<void, E>::map_error(Fn&& fn) && -> result<void, detail::invoke_result_t<Fn, E&&>>
4696 {
4697     using result_type = result<void, detail::invoke_result_t<Fn, E&&>>;
4698 
4699     return has_value()
4700         ? result_type{}
4701         : result_type(in_place_error,
4702                       detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error)));
4703 }
4704 
4705 template<typename E>
4706 template<typename Fn>
4707 inline RESULT_INLINE_VISIBILITY constexpr auto
4708 RESULT_NS_IMPL::result<void, E>::flat_map_error(Fn&& fn) const& -> detail::invoke_result_t<Fn, const E&>
4709 {
4710     using result_type = detail::invoke_result_t<Fn, const E&>;
4711 
4712     static_assert(is_result<result_type>::value,
4713                   "flat_map_error must return a result type or the program is ill-formed");
4714     static_assert(std::is_default_constructible<typename result_type::value_type>::value,
4715                   "flat_map_error for result<void,E> requires the new T type to be default-"
4716                   "constructible");
4717 
4718     return has_value() ? result_type{} : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
4719 }
4720 
4721 template<typename E>
4722 template<typename Fn>
4723 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4724 RESULT_NS_IMPL::result<void, E>::flat_map_error(Fn&& fn) && -> detail::invoke_result_t<Fn, E&&>
4725 {
4726     using result_type = detail::invoke_result_t<Fn, E&&>;
4727 
4728     static_assert(is_result<result_type>::value,
4729                   "flat_map_error must return a result type or the program is ill-formed");
4730     static_assert(std::is_default_constructible<typename result_type::value_type>::value,
4731                   "flat_map_error for result<void,E> requires the new T type to be default-"
4732                   "constructible");
4733 
4734     return has_value() ? result_type{}
4735                        : detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error));
4736 }
4737 
4738 //-----------------------------------------------------------------------------
4739 // Private Monadic Functions
4740 //-----------------------------------------------------------------------------
4741 
4742 template<typename E>
4743 template<typename Fn>
4744 inline RESULT_INLINE_VISIBILITY constexpr auto
4745 RESULT_NS_IMPL::result<void, E>::map_impl(std::true_type, Fn&& fn) const& -> result<void, E>
4746 {
4747     using result_type = result<void, E>;
4748 
4749     return has_value() ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
4750                        : result_type(in_place_error, m_storage.storage.m_error);
4751 }
4752 
4753 template<typename E>
4754 template<typename Fn>
4755 inline RESULT_INLINE_VISIBILITY constexpr auto
4756 RESULT_NS_IMPL::result<void, E>::map_impl(std::false_type, Fn&& fn) const& -> result<detail::invoke_result_t<Fn>, E>
4757 {
4758     using invoke_result_type = detail::invoke_result_t<Fn>;
4759     using result_type = result<invoke_result_type, E>;
4760 
4761     return has_value() ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
4762                        : result_type(in_place_error, m_storage.storage.m_error);
4763 }
4764 
4765 template<typename E>
4766 template<typename Fn>
4767 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4768 RESULT_NS_IMPL::result<void, E>::map_impl(std::true_type, Fn&& fn) && -> result<void, E>
4769 {
4770     using result_type = result<void, E>;
4771 
4772     return has_value() ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
4773                        : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4774 }
4775 
4776 template<typename E>
4777 template<typename Fn>
4778 inline RESULT_INLINE_VISIBILITY RESULT_CPP14_CONSTEXPR auto
4779 RESULT_NS_IMPL::result<void, E>::map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn>, E>
4780 {
4781     using invoke_result_type = detail::invoke_result_t<Fn>;
4782     using result_type = result<invoke_result_type, E>;
4783 
4784     return has_value() ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
4785                        : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4786 }
4787 
4788 //=============================================================================
4789 // non-member functions : class : result
4790 //=============================================================================
4791 
4792 //-----------------------------------------------------------------------------
4793 // Comparison
4794 //-----------------------------------------------------------------------------
4795 
4796 template<typename T1, typename E1, typename T2, typename E2>
4797 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator==(const result<T1, E1>& lhs,
4798                                                                           const result<T2, E2>& rhs) noexcept -> bool
4799 {
4800     return (lhs.has_value() == rhs.has_value())
4801         ? (lhs.has_value() ? *lhs == *rhs : detail::extract_error(lhs) == detail::extract_error(rhs))
4802         : false;
4803 }
4804 
4805 template<typename T1, typename E1, typename T2, typename E2>
4806 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator!=(const result<T1, E1>& lhs,
4807                                                                           const result<T2, E2>& rhs) noexcept -> bool
4808 {
4809     return (lhs.has_value() == rhs.has_value())
4810         ? (lhs.has_value() ? *lhs != *rhs : detail::extract_error(lhs) != detail::extract_error(rhs))
4811         : true;
4812 }
4813 
4814 template<typename T1, typename E1, typename T2, typename E2>
4815 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>=(const result<T1, E1>& lhs,
4816                                                                           const result<T2, E2>& rhs) noexcept -> bool
4817 {
4818     return (lhs.has_value() == rhs.has_value())
4819         ? (lhs.has_value() ? *lhs >= *rhs : detail::extract_error(lhs) >= detail::extract_error(rhs))
4820         : static_cast<int>(static_cast<bool>(lhs)) >= static_cast<int>(static_cast<bool>(rhs));
4821 }
4822 
4823 template<typename T1, typename E1, typename T2, typename E2>
4824 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<=(const result<T1, E1>& lhs,
4825                                                                           const result<T2, E2>& rhs) noexcept -> bool
4826 {
4827     return (lhs.has_value() == rhs.has_value())
4828         ? (lhs.has_value() ? *lhs <= *rhs : detail::extract_error(lhs) <= detail::extract_error(rhs))
4829         : static_cast<int>(static_cast<bool>(lhs)) <= static_cast<int>(static_cast<bool>(rhs));
4830 }
4831 
4832 template<typename T1, typename E1, typename T2, typename E2>
4833 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>(const result<T1, E1>& lhs,
4834                                                                          const result<T2, E2>& rhs) noexcept -> bool
4835 {
4836     return (lhs.has_value() == rhs.has_value())
4837         ? (lhs.has_value() ? *lhs > *rhs : detail::extract_error(lhs) > detail::extract_error(rhs))
4838         : static_cast<int>(static_cast<bool>(lhs)) > static_cast<int>(static_cast<bool>(rhs));
4839 }
4840 
4841 template<typename T1, typename E1, typename T2, typename E2>
4842 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<(const result<T1, E1>& lhs,
4843                                                                          const result<T2, E2>& rhs) noexcept -> bool
4844 {
4845     return (lhs.has_value() == rhs.has_value())
4846         ? (lhs.has_value() ? *lhs < *rhs : detail::extract_error(lhs) < detail::extract_error(rhs))
4847         : static_cast<int>(static_cast<bool>(lhs)) < static_cast<int>(static_cast<bool>(rhs));
4848 }
4849 
4850 //-----------------------------------------------------------------------------
4851 
4852 template<typename E1, typename E2>
4853 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator==(const result<void, E1>& lhs,
4854                                                                           const result<void, E2>& rhs) noexcept -> bool
4855 {
4856     return lhs.has_value() == rhs.has_value()
4857         ? (lhs.has_value() ? true : detail::extract_error(lhs) == detail::extract_error(rhs))
4858         : false;
4859 }
4860 
4861 template<typename E1, typename E2>
4862 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator!=(const result<void, E1>& lhs,
4863                                                                           const result<void, E2>& rhs) noexcept -> bool
4864 {
4865     return lhs.has_value() == rhs.has_value()
4866         ? (lhs.has_value() ? false : detail::extract_error(lhs) != detail::extract_error(rhs))
4867         : true;
4868 }
4869 
4870 template<typename E1, typename E2>
4871 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>=(const result<void, E1>& lhs,
4872                                                                           const result<void, E2>& rhs) noexcept -> bool
4873 {
4874     return lhs.has_value() == rhs.has_value()
4875         ? (lhs.has_value() ? true : detail::extract_error(lhs) >= detail::extract_error(rhs))
4876         : static_cast<int>(static_cast<bool>(lhs)) >= static_cast<int>(static_cast<bool>(rhs));
4877 }
4878 
4879 template<typename E1, typename E2>
4880 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<=(const result<void, E1>& lhs,
4881                                                                           const result<void, E2>& rhs) noexcept -> bool
4882 {
4883     return lhs.has_value() == rhs.has_value()
4884         ? (lhs.has_value() ? true : detail::extract_error(lhs) <= detail::extract_error(rhs))
4885         : static_cast<int>(static_cast<bool>(lhs)) <= static_cast<int>(static_cast<bool>(rhs));
4886 }
4887 
4888 template<typename E1, typename E2>
4889 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>(const result<void, E1>& lhs,
4890                                                                          const result<void, E2>& rhs) noexcept -> bool
4891 {
4892     return lhs.has_value() == rhs.has_value()
4893         ? (lhs.has_value() ? false : detail::extract_error(lhs) > detail::extract_error(rhs))
4894         : static_cast<int>(static_cast<bool>(lhs)) > static_cast<int>(static_cast<bool>(rhs));
4895 }
4896 
4897 template<typename E1, typename E2>
4898 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<(const result<void, E1>& lhs,
4899                                                                          const result<void, E2>& rhs) noexcept -> bool
4900 {
4901     return lhs.has_value() == rhs.has_value()
4902         ? (lhs.has_value() ? false : detail::extract_error(lhs) < detail::extract_error(rhs))
4903         : static_cast<int>(static_cast<bool>(lhs)) < static_cast<int>(static_cast<bool>(rhs));
4904 }
4905 
4906 //-----------------------------------------------------------------------------
4907 
4908 template<typename T, typename E, typename U, typename>
4909 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator==(const result<T, E>& exp,
4910                                                                           const U& value) noexcept -> bool
4911 {
4912     return (exp.has_value() && *exp == value);
4913 }
4914 
4915 template<typename T, typename U, typename E, typename>
4916 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator==(const T& value,
4917                                                                           const result<U, E>& exp) noexcept -> bool
4918 {
4919     return (exp.has_value() && *exp == value);
4920 }
4921 
4922 template<typename T, typename E, typename U, typename>
4923 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator!=(const result<T, E>& exp,
4924                                                                           const U& value) noexcept -> bool
4925 {
4926     return exp.has_value() ? *exp != value : true;
4927 }
4928 
4929 template<typename T, typename U, typename E, typename>
4930 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator!=(const T& value,
4931                                                                           const result<U, E>& exp) noexcept -> bool
4932 {
4933     return exp.has_value() ? value != *exp : true;
4934 }
4935 
4936 template<typename T, typename E, typename U, typename>
4937 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<=(const result<T, E>& exp,
4938                                                                           const U& value) noexcept -> bool
4939 {
4940     return exp.has_value() ? *exp <= value : false;
4941 }
4942 
4943 template<typename T, typename U, typename E, typename>
4944 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<=(const T& value,
4945                                                                           const result<U, E>& exp) noexcept -> bool
4946 {
4947     return exp.has_value() ? value <= *exp : true;
4948 }
4949 
4950 template<typename T, typename E, typename U, typename>
4951 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>=(const result<T, E>& exp,
4952                                                                           const U& value) noexcept -> bool
4953 {
4954     return exp.has_value() ? *exp >= value : true;
4955 }
4956 
4957 template<typename T, typename U, typename E, typename>
4958 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>=(const T& value,
4959                                                                           const result<U, E>& exp) noexcept -> bool
4960 {
4961     return exp.has_value() ? value >= *exp : false;
4962 }
4963 
4964 template<typename T, typename E, typename U, typename>
4965 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<(const result<T, E>& exp,
4966                                                                          const U& value) noexcept -> bool
4967 {
4968     return exp.has_value() ? *exp < value : false;
4969 }
4970 
4971 template<typename T, typename U, typename E, typename>
4972 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<(const T& value,
4973                                                                          const result<U, E>& exp) noexcept -> bool
4974 {
4975     return exp.has_value() ? value < *exp : true;
4976 }
4977 
4978 template<typename T, typename E, typename U, typename>
4979 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>(const result<T, E>& exp,
4980                                                                          const U& value) noexcept -> bool
4981 {
4982     return exp.has_value() ? *exp > value : false;
4983 }
4984 
4985 template<typename T, typename U, typename E, typename>
4986 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>(const T& value,
4987                                                                          const result<U, E>& exp) noexcept -> bool
4988 {
4989     return exp.has_value() ? value > *exp : true;
4990 }
4991 
4992 //-----------------------------------------------------------------------------
4993 
4994 template<typename T, typename E, typename U>
4995 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator==(const result<T, E>& exp,
4996                                                                           const failure<U>& error) noexcept -> bool
4997 {
4998     return exp.has_error() ? detail::extract_error(exp) == error.error() : false;
4999 }
5000 
5001 template<typename T, typename U, typename E>
5002 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator==(const failure<T>& error,
5003                                                                           const result<E, U>& exp) noexcept -> bool
5004 {
5005     return exp.has_error() ? error.error() == detail::extract_error(exp) : false;
5006 }
5007 
5008 template<typename T, typename E, typename U>
5009 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator!=(const result<T, E>& exp,
5010                                                                           const failure<U>& error) noexcept -> bool
5011 {
5012     return exp.has_error() ? detail::extract_error(exp) != error.error() : true;
5013 }
5014 
5015 template<typename T, typename U, typename E>
5016 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator!=(const failure<T>& error,
5017                                                                           const result<E, U>& exp) noexcept -> bool
5018 {
5019     return exp.has_error() ? error.error() != detail::extract_error(exp) : true;
5020 }
5021 
5022 template<typename T, typename E, typename U>
5023 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<=(const result<T, E>& exp,
5024                                                                           const failure<U>& error) noexcept -> bool
5025 {
5026     return exp.has_error() ? detail::extract_error(exp) <= error.error() : true;
5027 }
5028 
5029 template<typename T, typename U, typename E>
5030 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<=(const failure<T>& error,
5031                                                                           const result<E, U>& exp) noexcept -> bool
5032 {
5033     return exp.has_error() ? error.error() <= detail::extract_error(exp) : false;
5034 }
5035 
5036 template<typename T, typename E, typename U>
5037 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>=(const result<T, E>& exp,
5038                                                                           const failure<U>& error) noexcept -> bool
5039 {
5040     return exp.has_error() ? detail::extract_error(exp) >= error.error() : false;
5041 }
5042 
5043 template<typename T, typename U, typename E>
5044 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>=(const failure<T>& error,
5045                                                                           const result<E, U>& exp) noexcept -> bool
5046 {
5047     return exp.has_error() ? error.error() >= detail::extract_error(exp) : true;
5048 }
5049 
5050 template<typename T, typename E, typename U>
5051 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<(const result<T, E>& exp,
5052                                                                          const failure<U>& error) noexcept -> bool
5053 {
5054     return exp.has_error() ? detail::extract_error(exp) < error.error() : true;
5055 }
5056 
5057 template<typename T, typename U, typename E>
5058 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator<(const failure<T>& error,
5059                                                                          const result<E, U>& exp) noexcept -> bool
5060 {
5061     return exp.has_error() ? error.error() < detail::extract_error(exp) : false;
5062 }
5063 
5064 template<typename T, typename E, typename U>
5065 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>(const result<T, E>& exp,
5066                                                                          const failure<U>& error) noexcept -> bool
5067 {
5068     return exp.has_error() ? detail::extract_error(exp) > error.error() : false;
5069 }
5070 
5071 template<typename T, typename U, typename E>
5072 inline RESULT_INLINE_VISIBILITY constexpr auto RESULT_NS_IMPL::operator>(const failure<T>& error,
5073                                                                          const result<E, U>& exp) noexcept -> bool
5074 {
5075     return exp.has_error() ? error.error() > detail::extract_error(exp) : true;
5076 }
5077 
5078 //-----------------------------------------------------------------------------
5079 // Utilities
5080 //-----------------------------------------------------------------------------
5081 
5082 template<typename T, typename E>
5083 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::swap(result<T, E>& lhs, result<T, E>& rhs)
5084 #if __cplusplus >= 201703L
5085     noexcept(
5086         std::is_nothrow_move_constructible<result<T, E>>::value&& std::is_nothrow_move_assignable<result<T, E>>::value&&
5087             std::is_nothrow_swappable<T>::value&& std::is_nothrow_swappable<E>::value)
5088 #else
5089     noexcept(
5090         std::is_nothrow_move_constructible<result<T, E>>::value&& std::is_nothrow_move_assignable<result<T, E>>::value)
5091 #endif
5092         -> void
5093 {
5094     using std::swap;
5095 
5096     if (lhs.has_value() == rhs.has_value()) {
5097         if (lhs.has_value()) {
5098             swap(*lhs, *rhs);
5099         } else {
5100             auto& lhs_error = detail::result_error_extractor::get(lhs);
5101             auto& rhs_error = detail::result_error_extractor::get(rhs);
5102 
5103             swap(lhs_error, rhs_error);
5104         }
5105         // If both `result`s contain values, do nothing
5106     } else {
5107         auto temp = static_cast<result<T, E>&&>(lhs);
5108         lhs = static_cast<result<T, E>&&>(rhs);
5109         rhs = static_cast<result<T, E>&&>(temp);
5110     }
5111 }
5112 
5113 template<typename E>
5114 inline RESULT_INLINE_VISIBILITY auto RESULT_NS_IMPL::swap(result<void, E>& lhs, result<void, E>& rhs)
5115 #if __cplusplus >= 201703L
5116     noexcept(std::is_nothrow_move_constructible<result<void, E>>::value&&
5117                  std::is_nothrow_move_assignable<result<void, E>>::value&& std::is_nothrow_swappable<E>::value)
5118 #else
5119     noexcept(std::is_nothrow_move_constructible<result<void, E>>::value&&
5120                  std::is_nothrow_move_assignable<result<void, E>>::value)
5121 #endif
5122         -> void
5123 {
5124     using std::swap;
5125 
5126     if (lhs.has_value() == rhs.has_value()) {
5127         if (lhs.has_error()) {
5128             auto& lhs_error = detail::result_error_extractor::get(lhs);
5129             auto& rhs_error = detail::result_error_extractor::get(rhs);
5130 
5131             swap(lhs_error, rhs_error);
5132         }
5133         // If both `result`s contain values, do nothing
5134     } else {
5135         auto temp = static_cast<result<void, E>&&>(lhs);
5136         lhs = static_cast<result<void, E>&&>(rhs);
5137         rhs = static_cast<result<void, E>&&>(temp);
5138     }
5139 }
5140 
5141 #if defined(__clang__)
5142 #pragma clang diagnostic pop
5143 #endif
5144 
5145 #undef RESULT_NAMESPACE_INTERNAL
5146 #undef RESULT_NS_IMPL
5147 #undef RESULT_CPP14_CONSTEXPR
5148 #undef RESULT_CPP17_INLINE
5149 #undef RESULT_INLINE_VISIBILITY
5150 #undef RESULT_NODISCARD
5151 #undef RESULT_WARN_UNUSED
5152 
5153 #endif /* RESULT_RESULT_HPP */