/* A less simple result type (C) 2017-2021 Niall Douglas (20 commits) File Created: June 2017 Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef BOOST_OUTCOME_BASIC_OUTCOME_HPP #define BOOST_OUTCOME_BASIC_OUTCOME_HPP #include "config.hpp" #include "basic_result.hpp" #include "detail/basic_outcome_exception_observers.hpp" #include "detail/basic_outcome_failure_observers.hpp" #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" // Standardese markup confuses clang #endif BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN template // class basic_outcome; namespace detail { // May be reused by basic_outcome subclasses to save load on the compiler template struct outcome_predicates { using result = result_predicates; // Predicate for the implicit constructors to be available static constexpr bool implicit_constructors_enabled = // result::implicit_constructors_enabled // && !detail::is_implicitly_constructible // && !detail::is_implicitly_constructible // && !detail::is_implicitly_constructible // && !detail::is_implicitly_constructible; // Predicate for the value converting constructor to be available. template static constexpr bool enable_value_converting_constructor = // implicit_constructors_enabled // &&result::template enable_value_converting_constructor // && !detail::is_implicitly_constructible; // deliberately less tolerant of ambiguity than result's edition // Predicate for the error converting constructor to be available. template static constexpr bool enable_error_converting_constructor = // implicit_constructors_enabled // &&result::template enable_error_converting_constructor // && !detail::is_implicitly_constructible; // deliberately less tolerant of ambiguity than result's edition // Predicate for the error condition converting constructor to be available. template static constexpr bool enable_error_condition_converting_constructor = result::template enable_error_condition_converting_constructor // && !detail::is_implicitly_constructible; // Predicate for the exception converting constructor to be available. template static constexpr bool enable_exception_converting_constructor = // implicit_constructors_enabled // && !is_in_place_type_t>::value // not in place construction && !detail::is_implicitly_constructible && !detail::is_implicitly_constructible && detail::is_implicitly_constructible; // Predicate for the error + exception converting constructor to be available. template static constexpr bool enable_error_exception_converting_constructor = // implicit_constructors_enabled // && !is_in_place_type_t>::value // not in place construction && !detail::is_implicitly_constructible && detail::is_implicitly_constructible // && !detail::is_implicitly_constructible && detail::is_implicitly_constructible; // Predicate for the converting copy constructor from a compatible outcome to be available. template static constexpr bool enable_compatible_conversion = // (std::is_void::value || detail::is_explicitly_constructible::value_type>) // if our value types are constructible &&(std::is_void::value || detail::is_explicitly_constructible::error_type>) // if our error types are constructible &&(std::is_void::value || detail::is_explicitly_constructible::exception_type>) // if our exception types are constructible ; // Predicate for the converting constructor from a make_error_code() of the input to be available. template static constexpr bool enable_make_error_code_compatible_conversion = // trait::is_error_code_available>::value // if error type has an error code && !enable_compatible_conversion // and the normal compatible conversion is not available && (std::is_void::value || detail::is_explicitly_constructible::value_type>) // and if our value types are constructible &&detail::is_explicitly_constructible::type> // and our error type is constructible from a make_error_code() && (std::is_void::value || detail::is_explicitly_constructible::exception_type>); // and our exception types are constructible // Predicate for the implicit converting inplace constructor from a compatible input to be available. struct disable_inplace_value_error_exception_constructor; template using choose_inplace_value_error_exception_constructor = std::conditional_t< // ((static_cast(detail::is_constructible) + static_cast(detail::is_constructible) + static_cast(detail::is_constructible)) > 1), // disable_inplace_value_error_exception_constructor, // std::conditional_t< // detail::is_constructible, // value_type, // std::conditional_t< // detail::is_constructible, // error_type, // std::conditional_t< // detail::is_constructible, // exception_type, // disable_inplace_value_error_exception_constructor>>>>; template static constexpr bool enable_inplace_value_error_exception_constructor = // implicit_constructors_enabled && !std::is_same, disable_inplace_value_error_exception_constructor>::value; }; // Select whether to use basic_outcome_failure_observers or not template using select_basic_outcome_failure_observers = // std::conditional_t::value && trait::is_exception_ptr_available

::value, basic_outcome_failure_observers, Base>; template constexpr inline const V &extract_exception_from_failure(const failure_type &v) { return v.exception(); } template constexpr inline V &&extract_exception_from_failure(failure_type &&v) { return static_cast &&>(v).exception(); } template constexpr inline const U &extract_exception_from_failure(const failure_type &v) { return v.error(); } template constexpr inline U &&extract_exception_from_failure(failure_type &&v) { return static_cast &&>(v).error(); } template struct is_basic_outcome { static constexpr bool value = false; }; template struct is_basic_outcome> { static constexpr bool value = true; }; } // namespace detail /*! AWAITING HUGO JSON CONVERSION TOOL type alias template is_basic_outcome. Potential doc page: `is_basic_outcome` */ template using is_basic_outcome = detail::is_basic_outcome>; /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ template static constexpr bool is_basic_outcome_v = detail::is_basic_outcome>::value; namespace concepts { #if defined(__cpp_concepts) /* The `basic_outcome` concept. \requires That `U` matches a `basic_outcome`. */ template concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL basic_outcome = BOOST_OUTCOME_V2_NAMESPACE::is_basic_outcome::value || (requires(U v) { BOOST_OUTCOME_V2_NAMESPACE::basic_outcome(v); } && // detail::convertible< U, BOOST_OUTCOME_V2_NAMESPACE::basic_outcome> && // detail::base_of< BOOST_OUTCOME_V2_NAMESPACE::basic_outcome, U>); #else namespace detail { inline no_match match_basic_outcome(...); template >::value && // std::is_base_of, T>::value, bool> = true> inline BOOST_OUTCOME_V2_NAMESPACE::basic_outcome match_basic_outcome(BOOST_OUTCOME_V2_NAMESPACE::basic_outcome &&, T &&); template static constexpr bool basic_outcome = BOOST_OUTCOME_V2_NAMESPACE::is_basic_outcome::value || !std::is_same>(), std::declval>()))>::value; } // namespace detail /* The `basic_outcome` concept. \requires That `U` matches a `basic_outcome`. */ template static constexpr bool basic_outcome = detail::basic_outcome; #endif } // namespace concepts namespace hooks { /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ template constexpr inline void override_outcome_exception(basic_outcome *o, U &&v) noexcept; } // namespace hooks /*! AWAITING HUGO JSON CONVERSION TOOL type definition template basic_outcome. Potential doc page: `basic_outcome` */ template // class BOOST_OUTCOME_NODISCARD basic_outcome #if defined(BOOST_OUTCOME_DOXYGEN_IS_IN_THE_HOUSE) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) : public detail::basic_outcome_failure_observers, R, S, P, NoValuePolicy>, public detail::basic_outcome_exception_observers, R, S, P, NoValuePolicy>, public detail::basic_result_final #else : public detail::select_basic_outcome_failure_observers< detail::basic_outcome_exception_observers, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy> #endif { static_assert(trait::type_can_be_used_in_basic_result

, "The exception_type cannot be used"); static_assert(std::is_void

::value || std::is_default_constructible

::value, "exception_type must be void or default constructible"); using base = detail::select_basic_outcome_failure_observers< detail::basic_outcome_exception_observers, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>; friend struct policy::base; template // friend class basic_outcome; template friend constexpr inline void hooks::override_outcome_exception(basic_outcome *o, X &&v) noexcept; // NOLINT struct implicit_constructors_disabled_tag { }; struct value_converting_constructor_tag { }; struct error_converting_constructor_tag { }; struct error_condition_converting_constructor_tag { }; struct exception_converting_constructor_tag { }; struct error_exception_converting_constructor_tag { }; struct explicit_valueorerror_converting_constructor_tag { }; struct explicit_compatible_copy_conversion_tag { }; struct explicit_compatible_move_conversion_tag { }; struct explicit_make_error_code_compatible_copy_conversion_tag { }; struct explicit_make_error_code_compatible_move_conversion_tag { }; struct error_failure_tag { }; struct exception_failure_tag { }; struct disable_in_place_value_type { }; struct disable_in_place_error_type { }; struct disable_in_place_exception_type { }; public: using value_type = R; using error_type = S; using exception_type = P; using no_value_policy_type = NoValuePolicy; template using rebind = basic_outcome; protected: // Requirement predicates for outcome. struct predicate { using base = detail::outcome_predicates; // Predicate for any constructors to be available at all static constexpr bool constructors_enabled = (!std::is_same, std::decay_t>::value || (std::is_void::value && std::is_void::value)) // && (!std::is_same, std::decay_t>::value || (std::is_void::value && std::is_void::value)) // && (!std::is_same, std::decay_t>::value || (std::is_void::value && std::is_void::value)) // ; // Predicate for implicit constructors to be available at all static constexpr bool implicit_constructors_enabled = constructors_enabled && base::implicit_constructors_enabled; // Predicate for the value converting constructor to be available. template static constexpr bool enable_value_converting_constructor = // constructors_enabled // && !std::is_same, basic_outcome>::value // not my type && base::template enable_value_converting_constructor; // Predicate for the error converting constructor to be available. template static constexpr bool enable_error_converting_constructor = // constructors_enabled // && !std::is_same, basic_outcome>::value // not my type && base::template enable_error_converting_constructor; // Predicate for the error condition converting constructor to be available. template static constexpr bool enable_error_condition_converting_constructor = // constructors_enabled // && !std::is_same, basic_outcome>::value // not my type && base::template enable_error_condition_converting_constructor; // Predicate for the exception converting constructor to be available. template static constexpr bool enable_exception_converting_constructor = // constructors_enabled // && !std::is_same, basic_outcome>::value // not my type && base::template enable_exception_converting_constructor; // Predicate for the error + exception converting constructor to be available. template static constexpr bool enable_error_exception_converting_constructor = // constructors_enabled // && !std::is_same, basic_outcome>::value // not my type && base::template enable_error_exception_converting_constructor; // Predicate for the converting constructor from a compatible input to be available. template static constexpr bool enable_compatible_conversion = // constructors_enabled // && !std::is_same, basic_outcome>::value // not my type && base::template enable_compatible_conversion; // Predicate for the converting constructor from a make_error_code() of the input to be available. template static constexpr bool enable_make_error_code_compatible_conversion = // constructors_enabled // && !std::is_same, basic_outcome>::value // not my type && base::template enable_make_error_code_compatible_conversion; // Predicate for the inplace construction of value to be available. template static constexpr bool enable_inplace_value_constructor = // constructors_enabled // && (std::is_void::value // || detail::is_constructible); // Predicate for the inplace construction of error to be available. template static constexpr bool enable_inplace_error_constructor = // constructors_enabled // && (std::is_void::value // || detail::is_constructible); // Predicate for the inplace construction of exception to be available. template static constexpr bool enable_inplace_exception_constructor = // constructors_enabled // && (std::is_void::value // || detail::is_constructible); // Predicate for the implicit converting inplace constructor to be available. template static constexpr bool enable_inplace_value_error_exception_constructor = // constructors_enabled // &&base::template enable_inplace_value_error_exception_constructor; template using choose_inplace_value_error_exception_constructor = typename base::template choose_inplace_value_error_exception_constructor; }; public: using value_type_if_enabled = std::conditional_t::value || std::is_same::value, disable_in_place_value_type, value_type>; using error_type_if_enabled = std::conditional_t::value || std::is_same::value, disable_in_place_error_type, error_type>; using exception_type_if_enabled = std::conditional_t::value || std::is_same::value, disable_in_place_exception_type, exception_type>; protected: detail::devoid _ptr; public: /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class Arg, class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED((!predicate::constructors_enabled && sizeof...(Args) >= 0))) basic_outcome(Arg && /*unused*/, Args &&... /*unused*/) = delete; // NOLINT basic_outcome<> with any of the same type is NOT SUPPORTED, see docs! /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED((predicate::constructors_enabled && !predicate::implicit_constructors_enabled // && (detail::is_implicitly_constructible || detail::is_implicitly_constructible || detail::is_implicitly_constructible) ))) basic_outcome(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) = delete; // NOLINT Implicit constructors disabled, use explicit in_place_type, success() or failure(). see docs! /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_value_converting_constructor)) constexpr basic_outcome(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept( detail::is_nothrow_constructible) // NOLINT : base{in_place_type, static_cast(t)} , _ptr() { no_value_policy_type::on_outcome_construction(this, static_cast(t)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_converting_constructor)) constexpr basic_outcome(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept( detail::is_nothrow_constructible) // NOLINT : base{in_place_type, static_cast(t)} , _ptr() { no_value_policy_type::on_outcome_construction(this, static_cast(t)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class ErrorCondEnum) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), // BOOST_OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor)) constexpr basic_outcome(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept( noexcept(error_type(make_error_code(static_cast(t))))) // NOLINT : base{in_place_type, make_error_code(t)} { no_value_policy_type::on_outcome_construction(this, static_cast(t)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_exception_converting_constructor)) constexpr basic_outcome(T &&t, exception_converting_constructor_tag /*unused*/ = exception_converting_constructor_tag()) noexcept( detail::is_nothrow_constructible) // NOLINT : base() , _ptr(static_cast(t)) { this->_state._status.set_have_exception(true); no_value_policy_type::on_outcome_construction(this, static_cast(t)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_exception_converting_constructor)) constexpr basic_outcome(T &&a, U &&b, error_exception_converting_constructor_tag /*unused*/ = error_exception_converting_constructor_tag()) noexcept( detail::is_nothrow_constructible &&detail::is_nothrow_constructible) // NOLINT : base{in_place_type, static_cast(a)} , _ptr(static_cast(b)) { this->_state._status.set_have_exception(true); no_value_policy_type::on_outcome_construction(this, static_cast(a), static_cast(b)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(convert::value_or_error>::enable_result_inputs || !concepts::basic_result), // BOOST_OUTCOME_TPRED(convert::value_or_error>::enable_outcome_inputs || !concepts::basic_outcome), // BOOST_OUTCOME_TEXPR(convert::value_or_error>{}(std::declval()))) constexpr explicit basic_outcome(T &&o, explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT : basic_outcome{convert::value_or_error>{}(static_cast(o))} { } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion)) constexpr explicit basic_outcome( const basic_outcome &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible &&detail::is_nothrow_constructible &&detail::is_nothrow_constructible) : base{typename base::compatible_conversion_tag(), o} , _ptr(o._ptr) { no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion)) constexpr explicit basic_outcome( basic_outcome &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible &&detail::is_nothrow_constructible &&detail::is_nothrow_constructible) : base{typename base::compatible_conversion_tag(), static_cast &&>(o)} , _ptr(static_cast::exception_type &&>(o._ptr)) { no_value_policy_type::on_outcome_move_construction(this, static_cast &&>(o)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates::template enable_compatible_conversion)) constexpr explicit basic_outcome( const basic_result &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible &&detail::is_nothrow_constructible &&detail::is_nothrow_constructible) : base{typename base::compatible_conversion_tag(), o} , _ptr() { no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates::template enable_compatible_conversion)) constexpr explicit basic_outcome( basic_result &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible &&detail::is_nothrow_constructible &&detail::is_nothrow_constructible) : base{typename base::compatible_conversion_tag(), static_cast &&>(o)} , _ptr() { no_value_policy_type::on_outcome_move_construction(this, static_cast &&>(o)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates::template enable_make_error_code_compatible_conversion)) constexpr explicit basic_outcome(const basic_result &o, explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ = explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible &&noexcept(make_error_code(std::declval())) && detail::is_nothrow_constructible) : base{typename base::make_error_code_compatible_conversion_tag(), o} , _ptr() { no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates::template enable_make_error_code_compatible_conversion)) constexpr explicit basic_outcome(basic_result &&o, explicit_make_error_code_compatible_move_conversion_tag /*unused*/ = explicit_make_error_code_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible &&noexcept(make_error_code(std::declval())) && detail::is_nothrow_constructible) : base{typename base::make_error_code_compatible_conversion_tag(), static_cast &&>(o)} , _ptr() { no_value_policy_type::on_outcome_move_construction(this, static_cast &&>(o)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor)) constexpr explicit basic_outcome(in_place_type_t _, Args &&... args) noexcept(detail::is_nothrow_constructible) : base{_, static_cast(args)...} , _ptr() { no_value_policy_type::on_outcome_in_place_construction(this, in_place_type, static_cast(args)...); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class U, class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor, Args...>)) constexpr explicit basic_outcome(in_place_type_t _, std::initializer_list il, Args &&... args) noexcept(detail::is_nothrow_constructible, Args...>) : base{_, il, static_cast(args)...} , _ptr() { no_value_policy_type::on_outcome_in_place_construction(this, in_place_type, il, static_cast(args)...); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor)) constexpr explicit basic_outcome(in_place_type_t _, Args &&... args) noexcept(detail::is_nothrow_constructible) : base{_, static_cast(args)...} , _ptr() { no_value_policy_type::on_outcome_in_place_construction(this, in_place_type, static_cast(args)...); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class U, class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor, Args...>)) constexpr explicit basic_outcome(in_place_type_t _, std::initializer_list il, Args &&... args) noexcept(detail::is_nothrow_constructible, Args...>) : base{_, il, static_cast(args)...} , _ptr() { no_value_policy_type::on_outcome_in_place_construction(this, in_place_type, il, static_cast(args)...); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_exception_constructor)) constexpr explicit basic_outcome(in_place_type_t /*unused*/, Args &&... args) noexcept(detail::is_nothrow_constructible) : base() , _ptr(static_cast(args)...) { this->_state._status.set_have_exception(true); no_value_policy_type::on_outcome_in_place_construction(this, in_place_type, static_cast(args)...); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class U, class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_exception_constructor, Args...>)) constexpr explicit basic_outcome(in_place_type_t /*unused*/, std::initializer_list il, Args &&... args) noexcept(detail::is_nothrow_constructible, Args...>) : base() , _ptr(il, static_cast(args)...) { this->_state._status.set_have_exception(true); no_value_policy_type::on_outcome_in_place_construction(this, in_place_type, il, static_cast(args)...); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class A1, class A2, class... Args) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_error_exception_constructor)) constexpr basic_outcome(A1 &&a1, A2 &&a2, Args &&... args) noexcept( noexcept(typename predicate::template choose_inplace_value_error_exception_constructor(std::declval(), std::declval(), std::declval()...))) : basic_outcome(in_place_type>, static_cast(a1), static_cast(a2), static_cast(args)...) { } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ constexpr basic_outcome(const success_type &o) noexcept(std::is_nothrow_default_constructible::value) // NOLINT : base{in_place_type} { hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(const success_type &o) noexcept(detail::is_nothrow_constructible) // NOLINT : base{in_place_type, detail::extract_value_from_success(o)} { hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(success_type &&o) noexcept(detail::is_nothrow_constructible) // NOLINT : base{in_place_type, detail::extract_value_from_success(static_cast &&>(o))} { hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_move_construction(this, static_cast &&>(o)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(const failure_type &o, error_failure_tag /*unused*/ = error_failure_tag()) noexcept(detail::is_nothrow_constructible) // NOLINT : base{in_place_type, detail::extract_error_from_failure(o)} , _ptr() { hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(const failure_type &o, exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(detail::is_nothrow_constructible) // NOLINT : base() , _ptr(detail::extract_exception_from_failure(o)) { this->_state._status.set_have_exception(true); hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_make_error_code_compatible_conversion)) constexpr basic_outcome(const failure_type &o, explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ = explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(noexcept(make_error_code(std::declval()))) // NOLINT : base{in_place_type, make_error_code(detail::extract_error_from_failure(o))} , _ptr() { hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(const failure_type &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept( detail::is_nothrow_constructible &&detail::is_nothrow_constructible) // NOLINT : base{in_place_type, detail::extract_error_from_failure(o)} , _ptr(detail::extract_exception_from_failure(o)) { if(!o.has_error()) { this->_state._status.set_have_error(false); } if(o.has_exception()) { this->_state._status.set_have_exception(true); } hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(failure_type &&o, error_failure_tag /*unused*/ = error_failure_tag()) noexcept(detail::is_nothrow_constructible) // NOLINT : base{in_place_type, detail::extract_error_from_failure(static_cast &&>(o))} , _ptr() { hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(failure_type &&o, exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(detail::is_nothrow_constructible) // NOLINT : base() , _ptr(detail::extract_exception_from_failure(static_cast &&>(o))) { this->_state._status.set_have_exception(true); hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_make_error_code_compatible_conversion)) constexpr basic_outcome(failure_type &&o, explicit_make_error_code_compatible_move_conversion_tag /*unused*/ = explicit_make_error_code_compatible_move_conversion_tag()) noexcept(noexcept(make_error_code(std::declval()))) // NOLINT : base{in_place_type, make_error_code(detail::extract_error_from_failure(static_cast &&>(o)))} , _ptr() { hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_copy_construction(this, o); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void::value && predicate::template enable_compatible_conversion)) constexpr basic_outcome(failure_type &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept( detail::is_nothrow_constructible &&detail::is_nothrow_constructible) // NOLINT : base{in_place_type, detail::extract_error_from_failure(static_cast &&>(o))} , _ptr(detail::extract_exception_from_failure(static_cast &&>(o))) { if(!o.has_error()) { this->_state._status.set_have_error(false); } if(o.has_exception()) { this->_state._status.set_have_exception(true); } hooks::set_spare_storage(this, o.spare_storage()); no_value_policy_type::on_outcome_move_construction(this, static_cast &&>(o)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ using base::operator==; using base::operator!=; /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval>() == std::declval>()), // BOOST_OUTCOME_TEXPR(std::declval>() == std::declval>()), // BOOST_OUTCOME_TEXPR(std::declval>() == std::declval>())) constexpr bool operator==(const basic_outcome &o) const noexcept( // noexcept(std::declval>() == std::declval>()) // &&noexcept(std::declval>() == std::declval>()) // &&noexcept(std::declval>() == std::declval>())) { if(this->_state._status.have_value() && o._state._status.have_value()) { return this->_state._value == o._state._value; // NOLINT } if(this->_state._status.have_error() && o._state._status.have_error() // && this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_state._error == o._state._error && this->_ptr == o._ptr; } if(this->_state._status.have_error() && o._state._status.have_error()) { return this->_state._error == o._state._error; } if(this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_ptr == o._ptr; } return false; } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval() == std::declval()), // BOOST_OUTCOME_TEXPR(std::declval() == std::declval())) constexpr bool operator==(const failure_type &o) const noexcept( // noexcept(std::declval() == std::declval()) &&noexcept(std::declval() == std::declval())) { if(this->_state._status.have_error() && o._state._status.have_error() // && this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_state._error == o.error() && this->_ptr == o.exception(); } if(this->_state._status.have_error() && o._state._status.have_error()) { return this->_state._error == o.error(); } if(this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_ptr == o.exception(); } return false; } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval>() != std::declval>()), // BOOST_OUTCOME_TEXPR(std::declval>() != std::declval>()), // BOOST_OUTCOME_TEXPR(std::declval>() != std::declval>())) constexpr bool operator!=(const basic_outcome &o) const noexcept( // noexcept(std::declval>() != std::declval>()) // &&noexcept(std::declval>() != std::declval>()) // &&noexcept(std::declval>() != std::declval>())) { if(this->_state._status.have_value() && o._state._status.have_value()) { return this->_state._value != o._state._value; // NOLINT } if(this->_state._status.have_error() && o._state._status.have_error() // && this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_state._error != o._state._error || this->_ptr != o._ptr; } if(this->_state._status.have_error() && o._state._status.have_error()) { return this->_state._error != o._state._error; } if(this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_ptr != o._ptr; } return true; } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval() != std::declval()), // BOOST_OUTCOME_TEXPR(std::declval() != std::declval())) constexpr bool operator!=(const failure_type &o) const noexcept( // noexcept(std::declval() == std::declval()) &&noexcept(std::declval() == std::declval())) { if(this->_state._status.have_error() && o._state._status.have_error() // && this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_state._error != o.error() || this->_ptr != o.exception(); } if(this->_state._status.have_error() && o._state._status.have_error()) { return this->_state._error != o.error(); } if(this->_state._status.have_exception() && o._state._status.have_exception()) { return this->_ptr != o.exception(); } return true; } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ constexpr void swap(basic_outcome &o) noexcept((std::is_void::value || detail::is_nothrow_swappable::value) // && (std::is_void::value || detail::is_nothrow_swappable::value) // && (std::is_void::value || detail::is_nothrow_swappable::value)) { #ifndef BOOST_NO_EXCEPTIONS constexpr bool value_throws = !std::is_void::value && !detail::is_nothrow_swappable::value; constexpr bool error_throws = !std::is_void::value && !detail::is_nothrow_swappable::value; constexpr bool exception_throws = !std::is_void::value && !detail::is_nothrow_swappable::value; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4127) // conditional expression is constant #endif if(!exception_throws && !value_throws && !error_throws) { // Simples this->_state.swap(o._state); using std::swap; swap(this->_ptr, o._ptr); return; } struct _ { basic_outcome &a, &b; bool exceptioned{false}; bool all_good{false}; ~_() { if(!all_good) { // We lost one of the values a._state._status.set_have_lost_consistency(true); b._state._status.set_have_lost_consistency(true); return; } if(exceptioned) { // The value + error swap threw an exception. Try to swap back _ptr try { strong_swap(all_good, a._ptr, b._ptr); } catch(...) { // We lost one of the values a._state._status.set_have_lost_consistency(true); b._state._status.set_have_lost_consistency(true); // throw away second exception } // Prevent has_value() == has_error() or has_value() == has_exception() auto check = [](basic_outcome *t) { if(t->has_value() && (t->has_error() || t->has_exception())) { t->_state._status.set_have_error(false).set_have_exception(false); t->_state._status.set_have_lost_consistency(true); } if(!t->has_value() && !(t->has_error() || t->has_exception())) { // Choose error, for no particular reason t->_state._status.set_have_error(true).set_have_lost_consistency(true); } }; check(&a); check(&b); } } } _{*this, o}; strong_swap(_.all_good, this->_ptr, o._ptr); _.exceptioned = true; this->_state.swap(o._state); _.exceptioned = false; #ifdef _MSC_VER #pragma warning(pop) #endif #else this->_state.swap(o._state); using std::swap; swap(this->_ptr, o._ptr); #endif } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ failure_type as_failure() const & { if(this->has_error() && this->has_exception()) { return failure_type(this->assume_error(), this->assume_exception(), hooks::spare_storage(this)); } if(this->has_exception()) { return failure_type(in_place_type, this->assume_exception(), hooks::spare_storage(this)); } return failure_type(in_place_type, this->assume_error(), hooks::spare_storage(this)); } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ failure_type as_failure() && { this->_state._status.set_have_moved_from(true); if(this->has_error() && this->has_exception()) { return failure_type(static_cast(this->assume_error()), static_cast

(this->assume_exception()), hooks::spare_storage(this)); } if(this->has_exception()) { return failure_type(in_place_type, static_cast

(this->assume_exception()), hooks::spare_storage(this)); } return failure_type(in_place_type, static_cast(this->assume_error()), hooks::spare_storage(this)); } #ifdef __APPLE__ failure_type _xcode_workaround_as_failure() &&; #endif }; // C++ 20 operator== rewriting should take care of this for us, indeed // if we don't disable it, we cause Concept recursion to infinity! #if __cplusplus < 202000L && !_HAS_CXX20 /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V, // class R, class S, class P, class N) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval>() == std::declval>())) constexpr inline bool operator==(const basic_result &a, const basic_outcome &b) noexcept( // noexcept(std::declval>() == std::declval>())) { return b == a; } #endif /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ BOOST_OUTCOME_TEMPLATE(class T, class U, class V, // class R, class S, class P, class N) BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval>() != std::declval>())) constexpr inline bool operator!=(const basic_result &a, const basic_outcome &b) noexcept( // noexcept(std::declval>() != std::declval>())) { return b != a; } /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ template inline void swap(basic_outcome &a, basic_outcome &b) noexcept(noexcept(a.swap(b))) { a.swap(b); } namespace hooks { /*! AWAITING HUGO JSON CONVERSION TOOL SIGNATURE NOT RECOGNISED */ template constexpr inline void override_outcome_exception(basic_outcome *o, U &&v) noexcept { o->_ptr = static_cast(v); // NOLINT o->_state._status.set_have_exception(true); } } // namespace hooks BOOST_OUTCOME_V2_NAMESPACE_END #ifdef __clang__ #pragma clang diagnostic pop #endif #include "detail/basic_outcome_exception_observers_impl.hpp" #if !defined(NDEBUG) BOOST_OUTCOME_V2_NAMESPACE_BEGIN // Check is trivial in all ways except default constructibility and standard layout // static_assert(std::is_trivial>::value, "outcome is not trivial!"); // static_assert(std::is_trivially_default_constructible>::value, "outcome is not trivially default // constructible!"); static_assert(std::is_trivially_copyable>::value, "outcome is not trivially copyable!"); static_assert(std::is_trivially_assignable, basic_outcome>::value, "outcome is not trivially assignable!"); static_assert(std::is_trivially_destructible>::value, "outcome is not trivially destructible!"); static_assert(std::is_trivially_copy_constructible>::value, "outcome is not trivially copy constructible!"); static_assert(std::is_trivially_move_constructible>::value, "outcome is not trivially move constructible!"); static_assert(std::is_trivially_copy_assignable>::value, "outcome is not trivially copy assignable!"); static_assert(std::is_trivially_move_assignable>::value, "outcome is not trivially move assignable!"); // Can't be standard layout as non-static member data is defined in more than one inherited class // static_assert(std::is_standard_layout>::value, "outcome is not a standard layout type!"); BOOST_OUTCOME_V2_NAMESPACE_END #endif #endif