update boost
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/* Exception types throwable
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (9 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/* A very simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
|
||||
File Created: June 2017
|
||||
|
||||
|
||||
@@ -45,10 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
template <class R, class S, class NoValuePolicy> //
|
||||
#if !defined(__GNUC__) || __GNUC__ >= 8 // GCC's constraints implementation is buggy
|
||||
BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<R> &&trait::type_can_be_used_in_basic_result<S> && (std::is_void<S>::value || std::is_default_constructible<S>::value)) //
|
||||
#endif
|
||||
template <class R, class S, class NoValuePolicy> //
|
||||
class basic_result;
|
||||
|
||||
namespace detail
|
||||
@@ -56,13 +53,15 @@ namespace detail
|
||||
// These are reused by basic_outcome to save load on the compiler
|
||||
template <class value_type, class error_type> struct result_predicates
|
||||
{
|
||||
// Predicate for the implicit constructors to be available
|
||||
static constexpr bool implicit_constructors_enabled = //
|
||||
!(trait::is_error_type<std::decay_t<value_type>>::value && trait::is_error_type<std::decay_t<error_type>>::value) // both value and error types are not whitelisted error types
|
||||
&& ((!detail::is_implicitly_constructible<value_type, error_type> && !detail::is_implicitly_constructible<error_type, value_type>) // if value and error types cannot be constructed into one another
|
||||
|| (trait::is_error_type<std::decay_t<error_type>>::value // if error type is a whitelisted error type
|
||||
&& !detail::is_implicitly_constructible<error_type, value_type> // AND which cannot be constructed from the value type
|
||||
&& std::is_integral<value_type>::value)); // AND the value type is some integral type
|
||||
// Predicate for the implicit constructors to be available. Weakened to allow result<int, C enum>.
|
||||
static constexpr bool implicit_constructors_enabled = //
|
||||
!(trait::is_error_type<std::decay_t<value_type>>::value &&
|
||||
trait::is_error_type<std::decay_t<error_type>>::value) // both value and error types are not whitelisted error types
|
||||
&& ((!detail::is_implicitly_constructible<value_type, error_type> &&
|
||||
!detail::is_implicitly_constructible<error_type, value_type>) // if value and error types cannot be constructed into one another
|
||||
|| (trait::is_error_type<std::decay_t<error_type>>::value // if error type is a whitelisted error type
|
||||
&& !detail::is_implicitly_constructible<error_type, value_type> // AND which cannot be constructed from the value type
|
||||
&& std::is_integral<value_type>::value)); // AND the value type is some integral type
|
||||
|
||||
// Predicate for the value converting constructor to be available. Weakened to allow result<int, C enum>.
|
||||
template <class T>
|
||||
@@ -72,7 +71,7 @@ namespace detail
|
||||
&& !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
|
||||
&& ((detail::is_implicitly_constructible<value_type, T> && !detail::is_implicitly_constructible<error_type, T>) // is unambiguously for value type
|
||||
|| (std::is_same<value_type, std::decay_t<T>>::value // OR is my value type exactly
|
||||
&& detail::is_implicitly_constructible<value_type, T>) ); // and my value type is constructible from this ref form of T
|
||||
&& detail::is_implicitly_constructible<value_type, T>) ); // and my value type is constructible from this ref form of T
|
||||
|
||||
|
||||
// Predicate for the error converting constructor to be available. Weakened to allow result<int, C enum>.
|
||||
@@ -83,38 +82,64 @@ namespace detail
|
||||
&& !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
|
||||
&& ((!detail::is_implicitly_constructible<value_type, T> && detail::is_implicitly_constructible<error_type, T>) // is unambiguously for error type
|
||||
|| (std::is_same<error_type, std::decay_t<T>>::value // OR is my error type exactly
|
||||
&& detail::is_implicitly_constructible<error_type, T>) ); // and my error type is constructible from this ref form of T
|
||||
&& detail::is_implicitly_constructible<error_type, T>) ); // and my error type is constructible from this ref form of T
|
||||
|
||||
// Predicate for the error condition converting constructor to be available.
|
||||
template <class ErrorCondEnum>
|
||||
static constexpr bool enable_error_condition_converting_constructor = //
|
||||
!is_in_place_type_t<std::decay_t<ErrorCondEnum>>::value // not in place construction
|
||||
&& trait::is_error_type_enum<error_type, std::decay_t<ErrorCondEnum>>::value // is an error condition enum
|
||||
/*&& !detail::is_implicitly_constructible<value_type, ErrorCondEnum> && !detail::is_implicitly_constructible<error_type, ErrorCondEnum>*/; // not constructible via any other means
|
||||
static constexpr bool enable_error_condition_converting_constructor = //
|
||||
!is_in_place_type_t<std::decay_t<ErrorCondEnum>>::value // not in place construction
|
||||
&& trait::is_error_type_enum<error_type, std::decay_t<ErrorCondEnum>>::value // is an error condition enum
|
||||
/*&& !detail::is_implicitly_constructible<value_type, ErrorCondEnum> && !detail::is_implicitly_constructible<error_type, ErrorCondEnum>*/; // not
|
||||
// constructible
|
||||
// via any other
|
||||
// means
|
||||
|
||||
// Predicate for the converting copy constructor from a compatible input to be available.
|
||||
// Predicate for the converting constructor from a compatible input to be available.
|
||||
template <class T, class U, class V>
|
||||
static constexpr bool enable_compatible_conversion = //
|
||||
(std::is_void<T>::value || detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // if our value types are constructible
|
||||
&&(std::is_void<U>::value || detail::is_explicitly_constructible<error_type, typename basic_result<T, U, V>::error_type>) // if our error types are constructible
|
||||
static constexpr bool enable_compatible_conversion = //
|
||||
(std::is_void<T>::value ||
|
||||
detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // if our value types are constructible
|
||||
&&(std::is_void<U>::value ||
|
||||
detail::is_explicitly_constructible<error_type, typename basic_result<T, U, V>::error_type>) // if our error types are constructible
|
||||
;
|
||||
|
||||
// Predicate for the converting constructor from a make_error_code() of the input to be available.
|
||||
template <class T, class U, class V>
|
||||
static constexpr bool enable_make_error_code_compatible_conversion = //
|
||||
trait::is_error_code_available<std::decay_t<error_type>>::value // if error type has an error code
|
||||
&& !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
|
||||
&& (std::is_void<T>::value ||
|
||||
detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
|
||||
&&detail::is_explicitly_constructible<error_type,
|
||||
typename trait::is_error_code_available<U>::type>; // and our error type is constructible from a make_error_code()
|
||||
|
||||
// Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
|
||||
template <class T, class U, class V>
|
||||
static constexpr bool enable_make_exception_ptr_compatible_conversion = //
|
||||
trait::is_exception_ptr_available<std::decay_t<error_type>>::value // if error type has an exception ptr
|
||||
&& !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
|
||||
&& (std::is_void<T>::value ||
|
||||
detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
|
||||
&&detail::is_explicitly_constructible<error_type, typename trait::is_exception_ptr_available<U>::type>; // and our error type is constructible from a
|
||||
// make_exception_ptr()
|
||||
|
||||
// Predicate for the implicit converting inplace constructor from a compatible input to be available.
|
||||
struct disable_inplace_value_error_constructor;
|
||||
template <class... Args>
|
||||
using choose_inplace_value_error_constructor = std::conditional_t< //
|
||||
std::is_constructible<value_type, Args...>::value && std::is_constructible<error_type, Args...>::value, //
|
||||
disable_inplace_value_error_constructor, //
|
||||
std::conditional_t< //
|
||||
std::is_constructible<value_type, Args...>::value, //
|
||||
value_type, //
|
||||
std::conditional_t< //
|
||||
std::is_constructible<error_type, Args...>::value, //
|
||||
error_type, //
|
||||
using choose_inplace_value_error_constructor = std::conditional_t< //
|
||||
detail::is_constructible<value_type, Args...> && detail::is_constructible<error_type, Args...>, //
|
||||
disable_inplace_value_error_constructor, //
|
||||
std::conditional_t< //
|
||||
detail::is_constructible<value_type, Args...>, //
|
||||
value_type, //
|
||||
std::conditional_t< //
|
||||
detail::is_constructible<error_type, Args...>, //
|
||||
error_type, //
|
||||
disable_inplace_value_error_constructor>>>;
|
||||
template <class... Args>
|
||||
static constexpr bool enable_inplace_value_error_constructor = implicit_constructors_enabled //
|
||||
&& !std::is_same<choose_inplace_value_error_constructor<Args...>, disable_inplace_value_error_constructor>::value;
|
||||
static constexpr bool enable_inplace_value_error_constructor =
|
||||
implicit_constructors_enabled //
|
||||
&& !std::is_same<choose_inplace_value_error_constructor<Args...>, disable_inplace_value_error_constructor>::value;
|
||||
};
|
||||
|
||||
template <class T, class U> constexpr inline const U &extract_value_from_success(const success_type<U> &v) { return v.value(); }
|
||||
@@ -122,7 +147,10 @@ namespace detail
|
||||
template <class T> constexpr inline T extract_value_from_success(const success_type<void> & /*unused*/) { return T{}; }
|
||||
|
||||
template <class T, class U, class V> constexpr inline const U &extract_error_from_failure(const failure_type<U, V> &v) { return v.error(); }
|
||||
template <class T, class U, class V> constexpr inline U &&extract_error_from_failure(failure_type<U, V> &&v) { return static_cast<failure_type<U, V> &&>(v).error(); }
|
||||
template <class T, class U, class V> constexpr inline U &&extract_error_from_failure(failure_type<U, V> &&v)
|
||||
{
|
||||
return static_cast<failure_type<U, V> &&>(v).error();
|
||||
}
|
||||
template <class T, class V> constexpr inline T extract_error_from_failure(const failure_type<void, V> & /*unused*/) { return T{}; }
|
||||
|
||||
template <class T> struct is_basic_result
|
||||
@@ -144,6 +172,43 @@ SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T> static constexpr bool is_basic_result_v = detail::is_basic_result<std::decay_t<T>>::value;
|
||||
|
||||
namespace concepts
|
||||
{
|
||||
#if defined(__cpp_concepts)
|
||||
/* The `basic_result` concept.
|
||||
\requires That `U` matches a `basic_result`.
|
||||
*/
|
||||
template <class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL basic_result =
|
||||
BOOST_OUTCOME_V2_NAMESPACE::is_basic_result<U>::value ||
|
||||
(requires(U v) { BOOST_OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>(v); } && //
|
||||
detail::convertible<U, BOOST_OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>> && //
|
||||
detail::base_of<BOOST_OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>, U>);
|
||||
#else
|
||||
namespace detail
|
||||
{
|
||||
inline no_match match_basic_result(...);
|
||||
template <class R, class S, class NVP, class T, //
|
||||
typename = typename T::value_type, //
|
||||
typename = typename T::error_type, //
|
||||
typename = typename T::no_value_policy_type, //
|
||||
typename std::enable_if_t<std::is_convertible<T, BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP>>::value && //
|
||||
std::is_base_of<BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP>, T>::value,
|
||||
bool> = true>
|
||||
inline BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP> match_basic_result(BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP> &&, T &&);
|
||||
|
||||
template <class U>
|
||||
static constexpr bool basic_result = BOOST_OUTCOME_V2_NAMESPACE::is_basic_result<U>::value ||
|
||||
!std::is_same<no_match, decltype(match_basic_result(std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>(),
|
||||
std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
|
||||
} // namespace detail
|
||||
/* The `basic_result` concept.
|
||||
\requires That `U` matches a `basic_result`.
|
||||
*/
|
||||
template <class U> static constexpr bool basic_result = detail::basic_result<U>;
|
||||
#endif
|
||||
} // namespace concepts
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
@@ -152,42 +217,28 @@ namespace hooks
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_result_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_storage<R, S, NoValuePolicy> *r) noexcept
|
||||
{
|
||||
return r->_state._status.spare_storage_value;
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_result_copy_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_result_move_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U, class... Args> constexpr inline void hook_result_in_place_construction(T * /*unused*/, in_place_type_t<U> /*unused*/, Args &&... /*unused*/) noexcept {}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_final<R, S, NoValuePolicy> *r) noexcept { return (r->_state._status >> detail::status_2byte_shift) & 0xffff; }
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class R, class S, class NoValuePolicy> constexpr inline void set_spare_storage(detail::basic_result_final<R, S, NoValuePolicy> *r, uint16_t v) noexcept { r->_state._status |= (v << detail::status_2byte_shift); }
|
||||
template <class R, class S, class NoValuePolicy>
|
||||
constexpr inline void set_spare_storage(detail::basic_result_storage<R, S, NoValuePolicy> *r, uint16_t v) noexcept
|
||||
{
|
||||
r->_state._status.spare_storage_value = v;
|
||||
}
|
||||
} // namespace hooks
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type definition template <class R, class S, class NoValuePolicy> basic_result. Potential doc page: `basic_result<T, E, NoValuePolicy>`
|
||||
*/
|
||||
template <class R, class S, class NoValuePolicy> //
|
||||
#if !defined(__GNUC__) || __GNUC__ >= 8 // GCC's constraints implementation is buggy
|
||||
BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<R> &&trait::type_can_be_used_in_basic_result<S> && (std::is_void<S>::value || std::is_default_constructible<S>::value)) //
|
||||
#endif
|
||||
template <class R, class S, class NoValuePolicy> //
|
||||
class BOOST_OUTCOME_NODISCARD basic_result : public detail::basic_result_final<R, S, NoValuePolicy>
|
||||
{
|
||||
static_assert(trait::type_can_be_used_in_basic_result<R>, "The type R cannot be used in a basic_result");
|
||||
static_assert(trait::type_can_be_used_in_basic_result<S>, "The type S cannot be used in a basic_result");
|
||||
static_assert(std::is_void<S>::value || std::is_default_constructible<S>::value, "The type S must be void or default constructible");
|
||||
|
||||
using base = detail::basic_result_final<R, S, NoValuePolicy>;
|
||||
|
||||
@@ -209,10 +260,29 @@ class BOOST_OUTCOME_NODISCARD basic_result : public detail::basic_result_final<R
|
||||
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 explicit_make_exception_ptr_compatible_copy_conversion_tag
|
||||
{
|
||||
};
|
||||
struct explicit_make_exception_ptr_compatible_move_conversion_tag
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
using value_type = R;
|
||||
using error_type = S;
|
||||
using no_value_policy_type = NoValuePolicy;
|
||||
|
||||
using value_type_if_enabled = typename base::_value_type;
|
||||
using error_type_if_enabled = typename base::_error_type;
|
||||
@@ -252,26 +322,40 @@ protected:
|
||||
&& !std::is_same<std::decay_t<ErrorCondEnum>, basic_result>::value // not my type
|
||||
&& base::template enable_error_condition_converting_constructor<ErrorCondEnum>;
|
||||
|
||||
// Predicate for the converting copy constructor from a compatible input to be available.
|
||||
// Predicate for the converting constructor from a compatible input to be available.
|
||||
template <class T, class U, class V>
|
||||
static constexpr bool enable_compatible_conversion = //
|
||||
constructors_enabled //
|
||||
&& !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
|
||||
&& base::template enable_compatible_conversion<T, U, V>;
|
||||
|
||||
// Predicate for the converting constructor from a make_error_code() of the input to be available.
|
||||
template <class T, class U, class V>
|
||||
static constexpr bool enable_make_error_code_compatible_conversion = //
|
||||
constructors_enabled //
|
||||
&& !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
|
||||
&& base::template enable_make_error_code_compatible_conversion<T, U, V>;
|
||||
|
||||
// Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
|
||||
template <class T, class U, class V>
|
||||
static constexpr bool enable_make_exception_ptr_compatible_conversion = //
|
||||
constructors_enabled //
|
||||
&& !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
|
||||
&& base::template enable_make_exception_ptr_compatible_conversion<T, U, V>;
|
||||
|
||||
// Predicate for the inplace construction of value to be available.
|
||||
template <class... Args>
|
||||
static constexpr bool enable_inplace_value_constructor = //
|
||||
constructors_enabled //
|
||||
&& (std::is_void<value_type>::value //
|
||||
|| std::is_constructible<value_type, Args...>::value);
|
||||
|| detail::is_constructible<value_type, Args...>);
|
||||
|
||||
// Predicate for the inplace construction of error to be available.
|
||||
template <class... Args>
|
||||
static constexpr bool enable_inplace_error_constructor = //
|
||||
constructors_enabled //
|
||||
&& (std::is_void<error_type>::value //
|
||||
|| std::is_constructible<error_type, Args...>::value);
|
||||
|| detail::is_constructible<error_type, Args...>);
|
||||
|
||||
// Predicate for the implicit converting inplace constructor to be available.
|
||||
template <class... Args>
|
||||
@@ -317,29 +401,30 @@ 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<value_type, T> || detail::is_implicitly_constructible<error_type, T>) )))
|
||||
basic_result(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) = delete; // NOLINT Implicit constructors disabled, use explicit in_place_type<T>, success() or failure(). see docs!
|
||||
basic_result(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) =
|
||||
delete; // NOLINT Implicit constructors disabled, use explicit in_place_type<T>, 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<T>))
|
||||
constexpr basic_result(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
|
||||
: base{in_place_type<typename base::value_type>, static_cast<T &&>(t)}
|
||||
constexpr basic_result(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(
|
||||
detail::is_nothrow_constructible<value_type, T>) // NOLINT
|
||||
: base{in_place_type<typename base::value_type>, static_cast<T &&>(t)}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_construction(this, static_cast<T &&>(t));
|
||||
no_value_policy_type::on_result_construction(this, static_cast<T &&>(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<T>))
|
||||
constexpr basic_result(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
|
||||
: base{in_place_type<typename base::error_type>, static_cast<T &&>(t)}
|
||||
constexpr basic_result(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(
|
||||
detail::is_nothrow_constructible<error_type, T>) // NOLINT
|
||||
: base{in_place_type<typename base::error_type>, static_cast<T &&>(t)}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_construction(this, static_cast<T &&>(t));
|
||||
no_value_policy_type::on_result_construction(this, static_cast<T &&>(t));
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
@@ -347,21 +432,22 @@ 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<ErrorCondEnum>))
|
||||
constexpr basic_result(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
|
||||
: base{in_place_type<typename base::error_type>, make_error_code(t)}
|
||||
constexpr basic_result(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(
|
||||
noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
|
||||
: base{in_place_type<typename base::error_type>, make_error_code(t)}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_construction(this, static_cast<ErrorCondEnum &&>(t));
|
||||
no_value_policy_type::on_result_construction(this, static_cast<ErrorCondEnum &&>(t));
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(convert::value_or_error<basic_result, std::decay_t<T>>::enable_result_inputs || !is_basic_result_v<T>), //
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(convert::value_or_error<basic_result, std::decay_t<T>>::enable_result_inputs || !concepts::basic_result<T>), //
|
||||
BOOST_OUTCOME_TEXPR(convert::value_or_error<basic_result, std::decay_t<T>>{}(std::declval<T>())))
|
||||
constexpr explicit basic_result(T &&o, explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
|
||||
: basic_result{convert::value_or_error<basic_result, std::decay_t<T>>{}(static_cast<T &&>(o))}
|
||||
constexpr explicit basic_result(T &&o,
|
||||
explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
|
||||
: basic_result{convert::value_or_error<basic_result, std::decay_t<T>>{}(static_cast<T &&>(o))}
|
||||
{
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
@@ -369,22 +455,78 @@ SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V>))
|
||||
constexpr explicit basic_result(const basic_result<T, U, V> &o) noexcept(std::is_nothrow_constructible<value_type, T>::value &&std::is_nothrow_constructible<error_type, U>::value)
|
||||
constexpr explicit basic_result(
|
||||
const basic_result<T, U, V> &o,
|
||||
explicit_compatible_copy_conversion_tag /*unused*/ =
|
||||
explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>)
|
||||
: base{typename base::compatible_conversion_tag(), o}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_copy_construction(this, o);
|
||||
no_value_policy_type::on_result_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(predicate::template enable_compatible_conversion<T, U, V>))
|
||||
constexpr explicit basic_result(basic_result<T, U, V> &&o) noexcept(std::is_nothrow_constructible<value_type, T>::value &&std::is_nothrow_constructible<error_type, U>::value)
|
||||
constexpr explicit basic_result(
|
||||
basic_result<T, U, V> &&o,
|
||||
explicit_compatible_move_conversion_tag /*unused*/ =
|
||||
explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>)
|
||||
: base{typename base::compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
|
||||
no_value_policy_type::on_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
|
||||
constexpr explicit basic_result(const basic_result<T, U, V> &o,
|
||||
explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
|
||||
explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
|
||||
&&noexcept(make_error_code(std::declval<U>())))
|
||||
: base{typename base::make_error_code_compatible_conversion_tag(), o}
|
||||
{
|
||||
no_value_policy_type::on_result_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(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
|
||||
constexpr explicit basic_result(basic_result<T, U, V> &&o,
|
||||
explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
|
||||
explicit_make_error_code_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
|
||||
&&noexcept(make_error_code(std::declval<U>())))
|
||||
: base{typename base::make_error_code_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
|
||||
{
|
||||
no_value_policy_type::on_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
|
||||
constexpr explicit basic_result(const basic_result<T, U, V> &o,
|
||||
explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ =
|
||||
explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
|
||||
&&noexcept(make_exception_ptr(std::declval<U>())))
|
||||
: base{typename base::make_exception_ptr_compatible_conversion_tag(), o}
|
||||
{
|
||||
no_value_policy_type::on_result_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(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
|
||||
constexpr explicit basic_result(basic_result<T, U, V> &&o,
|
||||
explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ =
|
||||
explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
|
||||
&&noexcept(make_exception_ptr(std::declval<U>())))
|
||||
: base{typename base::make_exception_ptr_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
|
||||
{
|
||||
no_value_policy_type::on_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
@@ -392,134 +534,188 @@ SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class... Args)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<Args...>))
|
||||
constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args...>::value)
|
||||
constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, Args...>)
|
||||
: base{_, static_cast<Args &&>(args)...}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_in_place_construction(this, in_place_type<value_type>, static_cast<Args &&>(args)...);
|
||||
no_value_policy_type::on_result_in_place_construction(this, in_place_type<value_type>, static_cast<Args &&>(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<std::initializer_list<U>, Args...>))
|
||||
constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>::value)
|
||||
constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, std::initializer_list<U> il,
|
||||
Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>)
|
||||
: base{_, il, static_cast<Args &&>(args)...}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_in_place_construction(this, in_place_type<value_type>, il, static_cast<Args &&>(args)...);
|
||||
no_value_policy_type::on_result_in_place_construction(this, in_place_type<value_type>, il, static_cast<Args &&>(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<Args...>))
|
||||
constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, Args &&... args) noexcept(std::is_nothrow_constructible<error_type, Args...>::value)
|
||||
constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, Args...>)
|
||||
: base{_, static_cast<Args &&>(args)...}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_in_place_construction(this, in_place_type<error_type>, static_cast<Args &&>(args)...);
|
||||
no_value_policy_type::on_result_in_place_construction(this, in_place_type<error_type>, static_cast<Args &&>(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<std::initializer_list<U>, Args...>))
|
||||
constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<error_type, std::initializer_list<U>, Args...>::value)
|
||||
constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, std::initializer_list<U> il,
|
||||
Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, std::initializer_list<U>, Args...>)
|
||||
: base{_, il, static_cast<Args &&>(args)...}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_in_place_construction(this, in_place_type<error_type>, il, static_cast<Args &&>(args)...);
|
||||
no_value_policy_type::on_result_in_place_construction(this, in_place_type<error_type>, il, static_cast<Args &&>(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_constructor<A1, A2, Args...>))
|
||||
constexpr basic_result(A1 &&a1, A2 &&a2, Args &&... args) noexcept(noexcept(typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>(std::declval<A1>(), std::declval<A2>(), std::declval<Args>()...)))
|
||||
: basic_result(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, static_cast<A1 &&>(a1), static_cast<A2 &&>(a2), static_cast<Args &&>(args)...)
|
||||
constexpr basic_result(A1 &&a1, A2 &&a2, Args &&... args) noexcept(noexcept(
|
||||
typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>(std::declval<A1>(), std::declval<A2>(), std::declval<Args>()...)))
|
||||
: basic_result(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, static_cast<A1 &&>(a1),
|
||||
static_cast<A2 &&>(a2), static_cast<Args &&>(args)...)
|
||||
{
|
||||
/* I was a little surprised that the below is needed given that we forward to another constructor.
|
||||
But it turns out that ADL only fires on the first constructor for some reason.
|
||||
*/
|
||||
using namespace hooks;
|
||||
// hook_result_in_place_construction(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, this);
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
constexpr basic_result(const success_type<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value) // NOLINT
|
||||
: base{in_place_type<value_type_if_enabled>}
|
||||
: base{in_place_type<value_type_if_enabled>}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_copy_construction(this, o);
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_copy_construction(this, o);
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, void, void>))
|
||||
constexpr basic_result(const success_type<T> &o) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
|
||||
: base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(o)}
|
||||
constexpr basic_result(const success_type<T> &o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
|
||||
: base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(o)}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_copy_construction(this, o);
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_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<T>::value && predicate::template enable_compatible_conversion<T, void, void>))
|
||||
constexpr basic_result(success_type<T> &&o) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
|
||||
: base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
|
||||
constexpr basic_result(success_type<T> &&o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
|
||||
: base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_move_construction(this, static_cast<success_type<T> &&>(o));
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_move_construction(this, static_cast<success_type<T> &&>(o));
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
|
||||
constexpr basic_result(const failure_type<T> &o) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(o)}
|
||||
constexpr basic_result(const failure_type<T> &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(
|
||||
detail::is_nothrow_constructible<error_type, T>) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(o)}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_copy_construction(this, o);
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_copy_construction(this, o);
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
|
||||
constexpr basic_result(failure_type<T> &&o) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
|
||||
constexpr basic_result(failure_type<T> &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(
|
||||
detail::is_nothrow_constructible<error_type, T>) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
|
||||
{
|
||||
using namespace hooks;
|
||||
hook_result_move_construction(this, static_cast<failure_type<T> &&>(o));
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_move_construction(this, static_cast<failure_type<T> &&>(o));
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
|
||||
constexpr basic_result(const failure_type<T> &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<T>()))) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(o))}
|
||||
{
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_copy_construction(this, o);
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
|
||||
constexpr basic_result(failure_type<T> &&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<T>()))) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
|
||||
{
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_move_construction(this, static_cast<failure_type<T> &&>(o));
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
|
||||
constexpr basic_result(const failure_type<T> &o,
|
||||
explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ =
|
||||
explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(o))}
|
||||
{
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_copy_construction(this, o);
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
|
||||
constexpr basic_result(failure_type<T> &&o,
|
||||
explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ =
|
||||
explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
|
||||
: base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
|
||||
{
|
||||
hooks::set_spare_storage(this, o.spare_storage());
|
||||
no_value_policy_type::on_result_move_construction(this, static_cast<failure_type<T> &&>(o));
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
constexpr void swap(basic_result &o) noexcept(detail::is_nothrow_swappable<value_type>::value &&std::is_nothrow_move_constructible<value_type>::value //
|
||||
&&detail::is_nothrow_swappable<error_type>::value &&std::is_nothrow_move_constructible<error_type>::value)
|
||||
constexpr void swap(basic_result &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
|
||||
&& (std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value))
|
||||
{
|
||||
using std::swap;
|
||||
constexpr bool value_throws = !noexcept(this->_state.swap(o._state));
|
||||
constexpr bool error_throws = !noexcept(swap(this->_error, o._error));
|
||||
detail::basic_result_storage_swap<value_throws, error_throws>(*this, o);
|
||||
this->_state.swap(o._state);
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
auto as_failure() const & { return failure(this->assume_error()); }
|
||||
auto as_failure() const & { return failure(this->assume_error(), hooks::spare_storage(this)); }
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
auto as_failure() && { return failure(static_cast<basic_result &&>(*this).assume_error()); }
|
||||
auto as_failure() &&
|
||||
{
|
||||
this->_state._status.set_have_moved_from(true);
|
||||
return failure(static_cast<basic_result &&>(*this).assume_error(), hooks::spare_storage(this));
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
failure_type<error_type> _xcode_workaround_as_failure() &&;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
@@ -533,9 +729,11 @@ template <class R, class S, class P> inline void swap(basic_result<R, S, P> &a,
|
||||
#if !defined(NDEBUG)
|
||||
// Check is trivial in all ways except default constructibility
|
||||
// static_assert(std::is_trivial<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivial!");
|
||||
// static_assert(std::is_trivially_default_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially default constructible!");
|
||||
// static_assert(std::is_trivially_default_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially default
|
||||
// constructible!");
|
||||
static_assert(std::is_trivially_copyable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copyable!");
|
||||
static_assert(std::is_trivially_assignable<basic_result<int, long, policy::all_narrow>, basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially assignable!");
|
||||
static_assert(std::is_trivially_assignable<basic_result<int, long, policy::all_narrow>, basic_result<int, long, policy::all_narrow>>::value,
|
||||
"result<int> is not trivially assignable!");
|
||||
static_assert(std::is_trivially_destructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially destructible!");
|
||||
static_assert(std::is_trivially_copy_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy constructible!");
|
||||
static_assert(std::is_trivially_move_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move constructible!");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A less simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
|
||||
File Created: June 2017
|
||||
|
||||
|
||||
@@ -35,18 +35,24 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "boost_result.hpp"
|
||||
|
||||
#ifndef BOOST_SYSTEM_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
|
||||
#define BOOST_SYSTEM_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
|
||||
namespace boost
|
||||
{
|
||||
namespace system
|
||||
{
|
||||
// Implement the .failure() observer.
|
||||
inline boost::exception_ptr basic_outcome_failure_exception_from_error(const boost::system::error_code &ec) { return boost::copy_exception(boost::system::system_error(ec)); }
|
||||
inline boost::exception_ptr basic_outcome_failure_exception_from_error(const boost::system::error_code &ec)
|
||||
{
|
||||
return boost::copy_exception(boost::system::system_error(ec));
|
||||
}
|
||||
} // namespace system
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class R, class S = boost::system::error_code, class P = boost::exception_ptr, class NoValuePolicy = policy::default_policy<R, S, P>> //
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A very simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (10 commits)
|
||||
File Created: June 2017
|
||||
|
||||
|
||||
@@ -33,12 +33,13 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#include "boost/exception_ptr.hpp"
|
||||
#include "boost/system/system_error.hpp"
|
||||
#include "boost/exception_ptr.hpp"
|
||||
#include "boost/version.hpp"
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
namespace policy
|
||||
@@ -50,14 +51,7 @@ namespace policy
|
||||
inline boost::system::error_code make_error_code(boost::system::error_code v) { return v; }
|
||||
|
||||
/* Pass through `make_exception_ptr` function for `boost::exception_ptr`.
|
||||
The reason this needs to be here, declared before the rest of Outcome,
|
||||
is that there is no boost::make_exception_ptr as Boost still uses the old
|
||||
naming boost::copy_exception. Therefore the ADL discovered make_exception_ptr
|
||||
doesn't work, hence this hacky pre-declaration here.
|
||||
|
||||
I was tempted to just inject a boost::make_exception_ptr, but I can see
|
||||
Boost doing that itself at some point. This hack should keep working after.
|
||||
*/
|
||||
*/
|
||||
inline boost::exception_ptr make_exception_ptr(boost::exception_ptr v) { return v; }
|
||||
} // namespace detail
|
||||
} // namespace policy
|
||||
@@ -94,7 +88,7 @@ namespace detail
|
||||
#endif
|
||||
)
|
||||
{
|
||||
state._status |= status_error_is_errno;
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
}
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const boost::system::error_condition &error)
|
||||
@@ -105,14 +99,17 @@ namespace detail
|
||||
#endif
|
||||
)
|
||||
{
|
||||
state._status |= status_error_is_errno;
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
}
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const boost::system::errc::errc_t & /*unused*/) { state._status |= status_error_is_errno; }
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const boost::system::errc::errc_t & /*unused*/)
|
||||
{
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
namespace trait
|
||||
@@ -123,10 +120,12 @@ namespace trait
|
||||
template <> struct _is_error_code_available<boost::system::error_code>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
using type = boost::system::error_code;
|
||||
};
|
||||
template <> struct _is_exception_ptr_available<boost::exception_ptr>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
using type = boost::exception_ptr;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
@@ -154,18 +153,18 @@ namespace trait
|
||||
} // namespace trait
|
||||
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class R, class S = boost::system::error_code, class NoValuePolicy = policy::default_policy<R, S, void>> //
|
||||
using boost_result = basic_result<R, S, NoValuePolicy>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type alias template <class R, class S = boost::system::error_code> boost_unchecked. Potential doc page: `boost_unchecked<T, E = boost::system::error_code>`
|
||||
*/
|
||||
template <class R, class S = boost::system::error_code> using boost_unchecked = boost_result<R, S, policy::all_narrow>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type alias template <class R, class S = boost::system::error_code> boost_checked. Potential doc page: `boost_checked<T, E = boost::system::error_code>`
|
||||
*/
|
||||
template <class R, class S = boost::system::error_code> using boost_checked = boost_result<R, S, policy::throw_bad_result_access<S, void>>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Configure Boost.Outcome with Boost
|
||||
(C) 2015-2019 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
|
||||
(C) 2015-2023 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
|
||||
File Created: August 2015
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#ifndef BOOST_OUTCOME_V2_CONFIG_HPP
|
||||
#define BOOST_OUTCOME_V2_CONFIG_HPP
|
||||
|
||||
#include "version.hpp"
|
||||
#include "detail/version.hpp"
|
||||
|
||||
// Pull in detection of __MINGW64_VERSION_MAJOR
|
||||
#if defined(__MINGW32__) && !defined(DOXYGEN_IS_IN_THE_HOUSE)
|
||||
@@ -56,25 +56,29 @@ DEALINGS IN THE SOFTWARE.
|
||||
#ifndef BOOST_OUTCOME_SYMBOL_VISIBLE
|
||||
#define BOOST_OUTCOME_SYMBOL_VISIBLE BOOST_SYMBOL_VISIBLE
|
||||
#endif
|
||||
#ifdef __has_cpp_attribute
|
||||
#define BOOST_OUTCOME_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
|
||||
#else
|
||||
#define BOOST_OUTCOME_HAS_CPP_ATTRIBUTE(attr) (0)
|
||||
#endif
|
||||
// Weird that Boost.Config doesn't define a BOOST_NO_CXX17_NODISCARD
|
||||
#ifndef BOOST_OUTCOME_NODISCARD
|
||||
#ifdef __has_cpp_attribute
|
||||
#if __has_cpp_attribute(nodiscard)
|
||||
#if BOOST_OUTCOME_HAS_CPP_ATTRIBUTE(nodiscard)
|
||||
#define BOOST_OUTCOME_NODISCARD [[nodiscard]]
|
||||
#endif
|
||||
#elif defined(__clang__)
|
||||
#elif defined(__clang__) // deliberately not GCC
|
||||
#define BOOST_OUTCOME_NODISCARD __attribute__((warn_unused_result))
|
||||
#elif defined(_MSC_VER)
|
||||
// _Must_inspect_result_ expands into this
|
||||
#define BOOST_OUTCOME_NODISCARD \
|
||||
__declspec("SAL_name" \
|
||||
"(" \
|
||||
"\"_Must_inspect_result_\"" \
|
||||
"," \
|
||||
"\"\"" \
|
||||
"," \
|
||||
"\"2\"" \
|
||||
")") __declspec("SAL_begin") __declspec("SAL_post") __declspec("SAL_mustInspect") __declspec("SAL_post") __declspec("SAL_checkReturn") __declspec("SAL_end")
|
||||
#define BOOST_OUTCOME_NODISCARD \
|
||||
__declspec( \
|
||||
"SAL_name" \
|
||||
"(" \
|
||||
"\"_Must_inspect_result_\"" \
|
||||
"," \
|
||||
"\"\"" \
|
||||
"," \
|
||||
"\"2\"" \
|
||||
")") __declspec("SAL_begin") __declspec("SAL_post") __declspec("SAL_mustInspect") __declspec("SAL_post") __declspec("SAL_checkReturn") __declspec("SAL_end")
|
||||
#endif
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_NODISCARD
|
||||
@@ -107,13 +111,17 @@ DEALINGS IN THE SOFTWARE.
|
||||
#define BOOST_OUTCOME_TPRED(...) typename = std::enable_if_t<__VA_ARGS__>
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_REQUIRES
|
||||
#ifdef __cpp_concepts
|
||||
#define BOOST_OUTCOME_REQUIRES(...) requires __VA_ARGS__
|
||||
#if defined(__cpp_concepts) && (!defined(_MSC_VER) || _MSC_FULL_VER >= 192400000) // VS 2019 16.3 is broken here
|
||||
#define BOOST_OUTCOME_REQUIRES(...) requires(__VA_ARGS__)
|
||||
#else
|
||||
#define BOOST_OUTCOME_REQUIRES(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR
|
||||
#define BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR 220 // the v2.2 Outcome release
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#define BOOST_OUTCOME_V2
|
||||
@@ -123,34 +131,34 @@ namespace boost
|
||||
}
|
||||
}
|
||||
/*! The namespace of this Boost.Outcome v2.
|
||||
*/
|
||||
*/
|
||||
#define BOOST_OUTCOME_V2_NAMESPACE boost::outcome_v2
|
||||
/*! Expands into the appropriate namespace markup to enter the Boost.Outcome v2 namespace.
|
||||
*/
|
||||
#define BOOST_OUTCOME_V2_NAMESPACE_BEGIN \
|
||||
namespace boost \
|
||||
{ \
|
||||
namespace outcome_v2 \
|
||||
*/
|
||||
#define BOOST_OUTCOME_V2_NAMESPACE_BEGIN \
|
||||
namespace boost \
|
||||
{ \
|
||||
namespace outcome_v2 \
|
||||
{
|
||||
/*! Expands into the appropriate namespace markup to enter the C++ module
|
||||
exported Boost.Outcome v2 namespace.
|
||||
*/
|
||||
#define BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN \
|
||||
namespace boost \
|
||||
{ \
|
||||
namespace outcome_v2 \
|
||||
#define BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN \
|
||||
namespace boost \
|
||||
{ \
|
||||
namespace outcome_v2 \
|
||||
{
|
||||
/*! \brief Expands into the appropriate namespace markup to exit the Boost.Outcome v2 namespace.
|
||||
\ingroup config
|
||||
*/
|
||||
#define BOOST_OUTCOME_V2_NAMESPACE_END \
|
||||
} \
|
||||
#define BOOST_OUTCOME_V2_NAMESPACE_END \
|
||||
} \
|
||||
}
|
||||
|
||||
#include <cstdint> // for uint32_t etc
|
||||
#include <initializer_list>
|
||||
#include <iosfwd> // for future serialisation
|
||||
#include <new> // for placement in moves etc
|
||||
#include <iosfwd> // for future serialisation
|
||||
#include <new> // for placement in moves etc
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE
|
||||
@@ -191,6 +199,22 @@ template <class T> constexpr in_place_type_t<T> in_place_type{};
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_OUTCOME_USE_STD_ADDRESSOF) && !BOOST_OUTCOME_USE_STD_ADDRESSOF
|
||||
#define BOOST_OUTCOME_ADDRESS_OF(...) (&__VA_ARGS__)
|
||||
#else
|
||||
#include <memory> // for std::addressof
|
||||
#define BOOST_OUTCOME_ADDRESS_OF(...) std::addressof(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_TRIVIAL_ABI
|
||||
#if defined(STANDARDESE_IS_IN_THE_HOUSE) || __clang_major__ >= 7
|
||||
//! Defined to be `[[clang::trivial_abi]]` when on a new enough clang compiler. Usually automatic, can be overriden.
|
||||
#define BOOST_OUTCOME_TRIVIAL_ABI [[clang::trivial_abi]]
|
||||
#else
|
||||
#define BOOST_OUTCOME_TRIVIAL_ABI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
{
|
||||
@@ -272,6 +296,34 @@ namespace detail
|
||||
};
|
||||
template <class T, class U> static constexpr bool is_implicitly_constructible = _is_implicitly_constructible<T, U>::value;
|
||||
|
||||
template <class T, class... Args> struct _is_nothrow_constructible
|
||||
{
|
||||
static constexpr bool value = std::is_nothrow_constructible<T, Args...>::value;
|
||||
};
|
||||
template <class T> struct _is_nothrow_constructible<T, void>
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <> struct _is_nothrow_constructible<void, void>
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T, class... Args> static constexpr bool is_nothrow_constructible = _is_nothrow_constructible<T, Args...>::value;
|
||||
|
||||
template <class T, class... Args> struct _is_constructible
|
||||
{
|
||||
static constexpr bool value = std::is_constructible<T, Args...>::value;
|
||||
};
|
||||
template <class T> struct _is_constructible<T, void>
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <> struct _is_constructible<void, void>
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T, class... Args> static constexpr bool is_constructible = _is_constructible<T, Args...>::value;
|
||||
|
||||
#ifndef BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
|
||||
#if defined(_MSC_VER) && _HAS_CXX17
|
||||
#define BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 1 // MSVC always has std::is_nothrow_swappable
|
||||
@@ -295,18 +347,10 @@ namespace detail
|
||||
#if !defined(STANDARDESE_IS_IN_THE_HOUSE) && BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
|
||||
template <class T> using is_nothrow_swappable = std::is_nothrow_swappable<T>;
|
||||
#else
|
||||
namespace _is_nothrow_swappable
|
||||
template <class T> struct is_nothrow_swappable
|
||||
{
|
||||
using namespace std;
|
||||
template <class T> constexpr inline T &ldeclval();
|
||||
template <class T, class = void> struct is_nothrow_swappable : std::integral_constant<bool, false>
|
||||
{
|
||||
};
|
||||
template <class T> struct is_nothrow_swappable<T, decltype(swap(ldeclval<T>(), ldeclval<T>()))> : std::integral_constant<bool, noexcept(swap(ldeclval<T>(), ldeclval<T>()))>
|
||||
{
|
||||
};
|
||||
} // namespace _is_nothrow_swappable
|
||||
template <class T> using is_nothrow_swappable = _is_nothrow_swappable::is_nothrow_swappable<T>;
|
||||
static constexpr bool value = std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value;
|
||||
};
|
||||
#endif
|
||||
} // namespace detail
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Says how to convert value, error and exception types
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
|
||||
File Created: Nov 2017
|
||||
|
||||
|
||||
@@ -35,33 +35,60 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
namespace convert
|
||||
namespace concepts
|
||||
{
|
||||
#if defined(__cpp_concepts)
|
||||
/* The `ValueOrNone` concept.
|
||||
#if(defined(_MSC_VER) || defined(__clang__) || (defined(__GNUC__) && __cpp_concepts >= 201707) || BOOST_OUTCOME_FORCE_STD_BOOST_OUTCOME_C_CONCEPTS) && \
|
||||
!BOOST_OUTCOME_FORCE_LEGACY_GCC_BOOST_OUTCOME_C_CONCEPTS
|
||||
#define BOOST_OUTCOME_GCC6_CONCEPT_BOOL
|
||||
#else
|
||||
#ifndef BOOST_OUTCOME_SUPPRESS_LEGACY_CONCEPTS_WARNING
|
||||
#warning "WARNING: Legacy GCC concepts are known to fail to compile in a number of important situations!"
|
||||
#endif
|
||||
#define BOOST_OUTCOME_GCC6_CONCEPT_BOOL bool
|
||||
#endif
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL SameHelper = std::is_same<T, U>::value;
|
||||
template <class T, class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;
|
||||
template <class T, class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL convertible = std::is_convertible<T, U>::value;
|
||||
template <class T, class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL base_of = std::is_base_of<T, U>::value;
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/* The `value_or_none` concept.
|
||||
\requires That `U::value_type` exists and that `std::declval<U>().has_value()` returns a `bool` and `std::declval<U>().value()` exists.
|
||||
*/
|
||||
template <class U> concept bool ValueOrNone = requires(U a)
|
||||
{
|
||||
template <class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL value_or_none = requires(U a) {
|
||||
{
|
||||
a.has_value()
|
||||
}
|
||||
->bool;
|
||||
{a.value()};
|
||||
} -> detail::same_as<bool>;
|
||||
{
|
||||
a.value()
|
||||
};
|
||||
};
|
||||
/* The `ValueOrError` concept.
|
||||
/* The `value_or_error` concept.
|
||||
\requires That `U::value_type` and `U::error_type` exist;
|
||||
that `std::declval<U>().has_value()` returns a `bool`, `std::declval<U>().value()` and `std::declval<U>().error()` exists.
|
||||
*/
|
||||
template <class U> concept bool ValueOrError = requires(U a)
|
||||
{
|
||||
template <class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL value_or_error = requires(U a) {
|
||||
{
|
||||
a.has_value()
|
||||
}
|
||||
->bool;
|
||||
{a.value()};
|
||||
{a.error()};
|
||||
} -> detail::same_as<bool>;
|
||||
{
|
||||
a.value()
|
||||
};
|
||||
{
|
||||
a.error()
|
||||
};
|
||||
};
|
||||
|
||||
#else
|
||||
namespace detail
|
||||
{
|
||||
@@ -77,18 +104,37 @@ namespace convert
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<U>().has_value()), BOOST_OUTCOME_TEXPR(std::declval<U>().value()), BOOST_OUTCOME_TEXPR(std::declval<U>().error()))
|
||||
inline U match_value_or_error(U &&);
|
||||
|
||||
template <class U> static constexpr bool ValueOrNone = !std::is_same<no_match, decltype(match_value_or_none(std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
|
||||
template <class U> static constexpr bool ValueOrError = !std::is_same<no_match, decltype(match_value_or_error(std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
|
||||
template <class U>
|
||||
static constexpr bool value_or_none =
|
||||
!std::is_same<no_match, decltype(match_value_or_none(std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
|
||||
template <class U>
|
||||
static constexpr bool value_or_error =
|
||||
!std::is_same<no_match, decltype(match_value_or_error(std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
|
||||
} // namespace detail
|
||||
/* The `ValueOrNone` concept.
|
||||
/* The `value_or_none` concept.
|
||||
\requires That `U::value_type` exists and that `std::declval<U>().has_value()` returns a `bool` and `std::declval<U>().value()` exists.
|
||||
*/
|
||||
template <class U> static constexpr bool ValueOrNone = detail::ValueOrNone<U>;
|
||||
/* The `ValueOrError` concept.
|
||||
template <class U> static constexpr bool value_or_none = detail::value_or_none<U>;
|
||||
/* The `value_or_error` concept.
|
||||
\requires That `U::value_type` and `U::error_type` exist;
|
||||
that `std::declval<U>().has_value()` returns a `bool`, `std::declval<U>().value()` and `std::declval<U>().error()` exists.
|
||||
*/
|
||||
template <class U> static constexpr bool ValueOrError = detail::ValueOrError<U>;
|
||||
template <class U> static constexpr bool value_or_error = detail::value_or_error<U>;
|
||||
#endif
|
||||
} // namespace concepts
|
||||
|
||||
namespace convert
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
#if defined(__cpp_concepts)
|
||||
template <class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL ValueOrNone = concepts::value_or_none<U>;
|
||||
template <class U>
|
||||
concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL ValueOrError = concepts::value_or_error<U>;
|
||||
#else
|
||||
template <class U> static constexpr bool ValueOrNone = concepts::value_or_none<U>;
|
||||
template <class U> static constexpr bool ValueOrError = concepts::value_or_error<U>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
@@ -107,7 +153,7 @@ namespace convert
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type definition value_or_error. Potential doc page: NOT FOUND
|
||||
*/
|
||||
template <class T, class U> struct value_or_error
|
||||
@@ -115,11 +161,18 @@ type definition value_or_error. Potential doc page: NOT FOUND
|
||||
static constexpr bool enable_result_inputs = false;
|
||||
static constexpr bool enable_outcome_inputs = false;
|
||||
BOOST_OUTCOME_TEMPLATE(class X)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_same<U, std::decay_t<X>>::value //
|
||||
&&ValueOrError<U> //
|
||||
&& (std::is_void<typename std::decay_t<X>::value_type>::value || BOOST_OUTCOME_V2_NAMESPACE::detail::is_explicitly_constructible<typename T::value_type, typename std::decay_t<X>::value_type>) //
|
||||
&&(std::is_void<typename std::decay_t<X>::error_type>::value || BOOST_OUTCOME_V2_NAMESPACE::detail::is_explicitly_constructible<typename T::error_type, typename std::decay_t<X>::error_type>) ))
|
||||
constexpr T operator()(X &&v) { return v.has_value() ? detail::make_type<T, typename T::value_type>::value(static_cast<X &&>(v)) : detail::make_type<T, typename U::error_type>::error(static_cast<X &&>(v)); }
|
||||
BOOST_OUTCOME_TREQUIRES(
|
||||
BOOST_OUTCOME_TPRED(std::is_same<U, std::decay_t<X>>::value //
|
||||
&&concepts::value_or_error<U> //
|
||||
&& (std::is_void<typename std::decay_t<X>::value_type>::value ||
|
||||
BOOST_OUTCOME_V2_NAMESPACE::detail::is_explicitly_constructible<typename T::value_type, typename std::decay_t<X>::value_type>) //
|
||||
&&(std::is_void<typename std::decay_t<X>::error_type>::value ||
|
||||
BOOST_OUTCOME_V2_NAMESPACE::detail::is_explicitly_constructible<typename T::error_type, typename std::decay_t<X>::error_type>) ))
|
||||
constexpr T operator()(X &&v)
|
||||
{
|
||||
return v.has_value() ? detail::make_type<T, typename T::value_type>::value(static_cast<X &&>(v)) :
|
||||
detail::make_type<T, typename U::error_type>::error(static_cast<X &&>(v));
|
||||
}
|
||||
};
|
||||
} // namespace convert
|
||||
|
||||
|
||||
68
linx64/include/boost/outcome/coroutine_support.hpp
Normal file
68
linx64/include/boost/outcome/coroutine_support.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/* Tells C++ coroutines about Outcome's result
|
||||
(C) 2019-2023 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
|
||||
File Created: Oct 2019
|
||||
|
||||
|
||||
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_COROUTINE_SUPPORT_HPP
|
||||
#define BOOST_OUTCOME_COROUTINE_SUPPORT_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#define BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_BEGIN \
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN namespace awaitables \
|
||||
{
|
||||
//
|
||||
#define BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_EXPORT_BEGIN \
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN namespace awaitables \
|
||||
{
|
||||
//
|
||||
#define BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_END \
|
||||
} \
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include "utils.hpp"
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
namespace awaitables
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline bool error_is_set(std::error_code ec) noexcept { return !!ec; }
|
||||
inline std::error_code error_from_exception(std::exception_ptr &&ep, std::error_code not_matched) noexcept { return BOOST_OUTCOME_V2_NAMESPACE::error_from_exception(static_cast<std::exception_ptr &&>(ep), not_matched); }
|
||||
} // namespace detail
|
||||
} // namespace awaitables
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
#include "detail/coroutine_support.ipp"
|
||||
|
||||
#undef BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_BEGIN
|
||||
#undef BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_EXPORT_BEGIN
|
||||
#undef BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Exception observers for outcome type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (3 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Exception observers for outcome type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Failure observers for outcome type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "basic_result_storage.hpp"
|
||||
|
||||
#include <exception>
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
namespace detail
|
||||
@@ -42,15 +44,15 @@ namespace detail
|
||||
struct search_detail_adl
|
||||
{
|
||||
};
|
||||
BOOST_OUTCOME_TEMPLATE(class S) //
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(basic_outcome_failure_exception_from_error(std::declval<S>()))) //
|
||||
// Do NOT use template requirements here!
|
||||
template <class S, typename = decltype(basic_outcome_failure_exception_from_error(std::declval<S>()))>
|
||||
inline auto _delayed_lookup_basic_outcome_failure_exception_from_error(const S &ec, search_detail_adl /*unused*/)
|
||||
{
|
||||
// ADL discovered
|
||||
return basic_outcome_failure_exception_from_error(ec);
|
||||
}
|
||||
} // namespace adl
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1920 // VS2019
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1923 // VS2019
|
||||
// VS2017 and VS2019 with /permissive- chokes on the correct form due to over eager early instantiation.
|
||||
template <class S, class P> inline void _delayed_lookup_basic_outcome_failure_exception_from_error(...) { static_assert(sizeof(S) == 0, "No specialisation for these error and exception types available!"); }
|
||||
#else
|
||||
@@ -72,11 +74,11 @@ namespace detail
|
||||
try
|
||||
#endif
|
||||
{
|
||||
if((this->_state._status & detail::status_have_exception) != 0)
|
||||
if(this->_state._status.have_exception())
|
||||
{
|
||||
return this->assume_exception();
|
||||
}
|
||||
if((this->_state._status & detail::status_have_error) != 0)
|
||||
if(this->_state._status.have_error())
|
||||
{
|
||||
return _delayed_lookup_basic_outcome_failure_exception_from_error(this->assume_error(), adl::search_detail_adl());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Error observers for a very simple basic_result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
@@ -46,43 +46,43 @@ namespace detail
|
||||
constexpr error_type &assume_error() & noexcept
|
||||
{
|
||||
NoValuePolicy::narrow_error_check(static_cast<basic_result_error_observers &>(*this));
|
||||
return this->_error;
|
||||
return this->_state._error;
|
||||
}
|
||||
constexpr const error_type &assume_error() const &noexcept
|
||||
{
|
||||
NoValuePolicy::narrow_error_check(static_cast<const basic_result_error_observers &>(*this));
|
||||
return this->_error;
|
||||
return this->_state._error;
|
||||
}
|
||||
constexpr error_type &&assume_error() && noexcept
|
||||
{
|
||||
NoValuePolicy::narrow_error_check(static_cast<basic_result_error_observers &&>(*this));
|
||||
return static_cast<error_type &&>(this->_error);
|
||||
return static_cast<error_type &&>(this->_state._error);
|
||||
}
|
||||
constexpr const error_type &&assume_error() const &&noexcept
|
||||
{
|
||||
NoValuePolicy::narrow_error_check(static_cast<const basic_result_error_observers &&>(*this));
|
||||
return static_cast<const error_type &&>(this->_error);
|
||||
return static_cast<const error_type &&>(this->_state._error);
|
||||
}
|
||||
|
||||
constexpr error_type &error() &
|
||||
{
|
||||
NoValuePolicy::wide_error_check(static_cast<basic_result_error_observers &>(*this));
|
||||
return this->_error;
|
||||
return this->_state._error;
|
||||
}
|
||||
constexpr const error_type &error() const &
|
||||
{
|
||||
NoValuePolicy::wide_error_check(static_cast<const basic_result_error_observers &>(*this));
|
||||
return this->_error;
|
||||
return this->_state._error;
|
||||
}
|
||||
constexpr error_type &&error() &&
|
||||
{
|
||||
NoValuePolicy::wide_error_check(static_cast<basic_result_error_observers &&>(*this));
|
||||
return static_cast<error_type &&>(this->_error);
|
||||
return static_cast<error_type &&>(this->_state._error);
|
||||
}
|
||||
constexpr const error_type &&error() const &&
|
||||
{
|
||||
NoValuePolicy::wide_error_check(static_cast<const basic_result_error_observers &&>(*this));
|
||||
return static_cast<const error_type &&>(this->_error);
|
||||
return static_cast<const error_type &&>(this->_state._error);
|
||||
}
|
||||
};
|
||||
template <class Base, class NoValuePolicy> class basic_result_error_observers<Base, void, NoValuePolicy> : public Base
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Finaliser for a very simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
@@ -53,11 +53,12 @@ namespace detail
|
||||
public:
|
||||
using base::base;
|
||||
|
||||
constexpr explicit operator bool() const noexcept { return (this->_state._status & detail::status_have_value) != 0; }
|
||||
constexpr bool has_value() const noexcept { return (this->_state._status & detail::status_have_value) != 0; }
|
||||
constexpr bool has_error() const noexcept { return (this->_state._status & detail::status_have_error) != 0; }
|
||||
constexpr bool has_exception() const noexcept { return (this->_state._status & detail::status_have_exception) != 0; }
|
||||
constexpr bool has_failure() const noexcept { return (this->_state._status & detail::status_have_error) != 0 || (this->_state._status & detail::status_have_exception) != 0; }
|
||||
constexpr explicit operator bool() const noexcept { return this->_state._status.have_value(); }
|
||||
constexpr bool has_value() const noexcept { return this->_state._status.have_value(); }
|
||||
constexpr bool has_error() const noexcept { return this->_state._status.have_error(); }
|
||||
constexpr bool has_exception() const noexcept { return this->_state._status.have_exception(); }
|
||||
constexpr bool has_lost_consistency() const noexcept { return this->_state._status.have_lost_consistency(); }
|
||||
constexpr bool has_failure() const noexcept { return this->_state._status.have_error() || this->_state._status.have_exception(); }
|
||||
|
||||
BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<R>>() == std::declval<detail::devoid<T>>()), //
|
||||
@@ -65,13 +66,13 @@ namespace detail
|
||||
constexpr bool operator==(const basic_result_final<T, U, V> &o) const noexcept( //
|
||||
noexcept(std::declval<detail::devoid<R>>() == std::declval<detail::devoid<T>>()) && noexcept(std::declval<detail::devoid<S>>() == std::declval<detail::devoid<U>>()))
|
||||
{
|
||||
if((this->_state._status & detail::status_have_value) != 0 && (o._state._status & detail::status_have_value) != 0)
|
||||
if(this->_state._status.have_value() && o._state._status.have_value())
|
||||
{
|
||||
return this->_state._value == o._state._value; // NOLINT
|
||||
}
|
||||
if((this->_state._status & detail::status_have_error) != 0 && (o._state._status & detail::status_have_error) != 0)
|
||||
if(this->_state._status.have_error() && o._state._status.have_error())
|
||||
{
|
||||
return this->_error == o._error;
|
||||
return this->_state._error == o._state._error;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -80,7 +81,7 @@ namespace detail
|
||||
constexpr bool operator==(const success_type<T> &o) const noexcept( //
|
||||
noexcept(std::declval<R>() == std::declval<T>()))
|
||||
{
|
||||
if((this->_state._status & detail::status_have_value) != 0)
|
||||
if(this->_state._status.have_value())
|
||||
{
|
||||
return this->_state._value == o.value();
|
||||
}
|
||||
@@ -89,16 +90,16 @@ namespace detail
|
||||
constexpr bool operator==(const success_type<void> &o) const noexcept
|
||||
{
|
||||
(void) o;
|
||||
return (this->_state._status & detail::status_have_value) != 0;
|
||||
return this->_state._status.have_value();
|
||||
}
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<S>() == std::declval<T>()))
|
||||
constexpr bool operator==(const failure_type<T, void> &o) const noexcept( //
|
||||
noexcept(std::declval<S>() == std::declval<T>()))
|
||||
{
|
||||
if((this->_state._status & detail::status_have_error) != 0)
|
||||
if(this->_state._status.have_error())
|
||||
{
|
||||
return this->_error == o.error();
|
||||
return this->_state._error == o.error();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -108,13 +109,13 @@ namespace detail
|
||||
constexpr bool operator!=(const basic_result_final<T, U, V> &o) const noexcept( //
|
||||
noexcept(std::declval<detail::devoid<R>>() != std::declval<detail::devoid<T>>()) && noexcept(std::declval<detail::devoid<S>>() != std::declval<detail::devoid<U>>()))
|
||||
{
|
||||
if((this->_state._status & detail::status_have_value) != 0 && (o._state._status & detail::status_have_value) != 0)
|
||||
if(this->_state._status.have_value() && o._state._status.have_value())
|
||||
{
|
||||
return this->_state._value != o._state._value;
|
||||
}
|
||||
if((this->_state._status & detail::status_have_error) != 0 && (o._state._status & detail::status_have_error) != 0)
|
||||
if(this->_state._status.have_error() && o._state._status.have_error())
|
||||
{
|
||||
return this->_error != o._error;
|
||||
return this->_state._error != o._state._error;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -123,7 +124,7 @@ namespace detail
|
||||
constexpr bool operator!=(const success_type<T> &o) const noexcept( //
|
||||
noexcept(std::declval<R>() != std::declval<T>()))
|
||||
{
|
||||
if((this->_state._status & detail::status_have_value) != 0)
|
||||
if(this->_state._status.have_value())
|
||||
{
|
||||
return this->_state._value != o.value();
|
||||
}
|
||||
@@ -132,16 +133,16 @@ namespace detail
|
||||
constexpr bool operator!=(const success_type<void> &o) const noexcept
|
||||
{
|
||||
(void) o;
|
||||
return (this->_state._status & detail::status_have_value) == 0;
|
||||
return !this->_state._status.have_value();
|
||||
}
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<S>() != std::declval<T>()))
|
||||
constexpr bool operator!=(const failure_type<T, void> &o) const noexcept( //
|
||||
noexcept(std::declval<S>() != std::declval<T>()))
|
||||
{
|
||||
if((this->_state._status & detail::status_have_error) != 0)
|
||||
if(this->_state._status.have_error())
|
||||
{
|
||||
return this->_error != o.error();
|
||||
return this->_state._error != o.error();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Storage for a very simple basic_result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@ BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class State, class E> constexpr inline void _set_error_is_errno(State & /*unused*/, const E & /*unused*/) {}
|
||||
template <class R, class S, class NoValuePolicy> class basic_result_final;
|
||||
template <class R, class EC, class NoValuePolicy> class basic_result_storage;
|
||||
} // namespace detail
|
||||
|
||||
namespace hooks
|
||||
{
|
||||
template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_final<R, S, NoValuePolicy> *r) noexcept;
|
||||
template <class R, class S, class NoValuePolicy> constexpr inline void set_spare_storage(detail::basic_result_final<R, S, NoValuePolicy> *r, uint16_t v) noexcept;
|
||||
template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_storage<R, S, NoValuePolicy> *r) noexcept;
|
||||
template <class R, class S, class NoValuePolicy>
|
||||
constexpr inline void set_spare_storage(detail::basic_result_storage<R, S, NoValuePolicy> *r, uint16_t v) noexcept;
|
||||
} // namespace hooks
|
||||
|
||||
namespace policy
|
||||
@@ -56,21 +56,20 @@ namespace policy
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool value_throws, bool error_throws> struct basic_result_storage_swap;
|
||||
template <class R, class EC, class NoValuePolicy> //
|
||||
BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<R> &&trait::type_can_be_used_in_basic_result<EC> && (std::is_void<EC>::value || std::is_default_constructible<EC>::value)) //
|
||||
template <class R, class EC, class NoValuePolicy> //
|
||||
class basic_result_storage
|
||||
{
|
||||
static_assert(trait::type_can_be_used_in_basic_result<R>, "The type R cannot be used in a basic_result");
|
||||
static_assert(trait::type_can_be_used_in_basic_result<EC>, "The type S cannot be used in a basic_result");
|
||||
static_assert(std::is_void<EC>::value || std::is_default_constructible<EC>::value, "The type S must be void or default constructible");
|
||||
|
||||
friend struct policy::base;
|
||||
template <class T, class U, class V> friend class basic_result_storage;
|
||||
template <class T, class U, class V> //
|
||||
friend class basic_result_storage;
|
||||
template <class T, class U, class V> friend class basic_result_final;
|
||||
template <class T, class U, class V> friend constexpr inline uint16_t hooks::spare_storage(const detail::basic_result_final<T, U, V> *r) noexcept; // NOLINT
|
||||
template <class T, class U, class V> friend constexpr inline void hooks::set_spare_storage(detail::basic_result_final<T, U, V> *r, uint16_t v) noexcept; // NOLINT
|
||||
template <bool value_throws, bool error_throws> struct basic_result_storage_swap;
|
||||
template <class T, class U, class V>
|
||||
friend constexpr inline uint16_t hooks::spare_storage(const detail::basic_result_storage<T, U, V> *r) noexcept; // NOLINT
|
||||
template <class T, class U, class V>
|
||||
friend constexpr inline void hooks::set_spare_storage(detail::basic_result_storage<T, U, V> *r, uint16_t v) noexcept; // NOLINT
|
||||
|
||||
struct disable_in_place_value_type
|
||||
{
|
||||
@@ -83,21 +82,18 @@ namespace detail
|
||||
using _value_type = std::conditional_t<std::is_same<R, EC>::value, disable_in_place_value_type, R>;
|
||||
using _error_type = std::conditional_t<std::is_same<R, EC>::value, disable_in_place_error_type, EC>;
|
||||
|
||||
using _state_type = value_storage_select_impl<_value_type, _error_type>;
|
||||
|
||||
#ifdef BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE
|
||||
detail::value_storage_trivial<_value_type> _state;
|
||||
value_storage_trivial<_value_type, _error_type> _state;
|
||||
#else
|
||||
detail::value_storage_select_impl<_value_type> _state;
|
||||
_state_type _state;
|
||||
#endif
|
||||
detail::devoid<_error_type> _error;
|
||||
|
||||
public:
|
||||
// Used by iostream support to access state
|
||||
detail::value_storage_select_impl<_value_type> &_iostreams_state() { return _state; }
|
||||
const detail::value_storage_select_impl<_value_type> &_iostreams_state() const { return _state; }
|
||||
|
||||
// Hack to work around MSVC bug in /permissive-
|
||||
detail::value_storage_select_impl<_value_type> &_msvc_nonpermissive_state() { return _state; }
|
||||
detail::devoid<_error_type> &_msvc_nonpermissive_error() { return _error; }
|
||||
_state_type &_iostreams_state() { return _state; }
|
||||
const _state_type &_iostreams_state() const { return _state; }
|
||||
|
||||
protected:
|
||||
basic_result_storage() = default;
|
||||
@@ -108,148 +104,82 @@ namespace detail
|
||||
~basic_result_storage() = default;
|
||||
|
||||
template <class... Args>
|
||||
constexpr explicit basic_result_storage(in_place_type_t<_value_type> _, Args &&... args) noexcept(std::is_nothrow_constructible<_value_type, Args...>::value)
|
||||
constexpr explicit basic_result_storage(in_place_type_t<_value_type> _,
|
||||
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type, Args...>)
|
||||
: _state{_, static_cast<Args &&>(args)...}
|
||||
, _error()
|
||||
{
|
||||
}
|
||||
template <class U, class... Args>
|
||||
constexpr basic_result_storage(in_place_type_t<_value_type> _, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<_value_type, std::initializer_list<U>, Args...>::value)
|
||||
constexpr basic_result_storage(in_place_type_t<_value_type> _, std::initializer_list<U> il,
|
||||
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type, std::initializer_list<U>, Args...>)
|
||||
: _state{_, il, static_cast<Args &&>(args)...}
|
||||
, _error()
|
||||
{
|
||||
}
|
||||
template <class... Args>
|
||||
constexpr explicit basic_result_storage(in_place_type_t<_error_type> /*unused*/, Args &&... args) noexcept(std::is_nothrow_constructible<_error_type, Args...>::value)
|
||||
: _state{detail::status_have_error}
|
||||
, _error(static_cast<Args &&>(args)...)
|
||||
constexpr explicit basic_result_storage(in_place_type_t<_error_type> _,
|
||||
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type, Args...>)
|
||||
: _state{_, static_cast<Args &&>(args)...}
|
||||
{
|
||||
_set_error_is_errno(_state, _error);
|
||||
}
|
||||
template <class U, class... Args>
|
||||
constexpr basic_result_storage(in_place_type_t<_error_type> /*unused*/, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<_error_type, std::initializer_list<U>, Args...>::value)
|
||||
: _state{detail::status_have_error}
|
||||
, _error{il, static_cast<Args &&>(args)...}
|
||||
constexpr basic_result_storage(in_place_type_t<_error_type> _, std::initializer_list<U> il,
|
||||
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type, std::initializer_list<U>, Args...>)
|
||||
: _state{_, il, static_cast<Args &&>(args)...}
|
||||
{
|
||||
_set_error_is_errno(_state, _error);
|
||||
}
|
||||
|
||||
struct compatible_conversion_tag
|
||||
{
|
||||
};
|
||||
template <class T, class U, class V>
|
||||
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, const basic_result_storage<T, U, V> &o) noexcept(std::is_nothrow_constructible<_value_type, T>::value &&std::is_nothrow_constructible<_error_type, U>::value)
|
||||
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, const basic_result_storage<T, U, V> &o) noexcept(
|
||||
detail::is_nothrow_constructible<_value_type, T> &&detail::is_nothrow_constructible<_error_type, U>)
|
||||
: _state(o._state)
|
||||
, _error(o._error)
|
||||
{
|
||||
}
|
||||
template <class T, class V>
|
||||
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, const basic_result_storage<T, void, V> &o) noexcept(std::is_nothrow_constructible<_value_type, T>::value)
|
||||
: _state(o._state)
|
||||
, _error(_error_type{})
|
||||
{
|
||||
}
|
||||
template <class T, class U, class V>
|
||||
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, basic_result_storage<T, U, V> &&o) noexcept(std::is_nothrow_constructible<_value_type, T>::value &&std::is_nothrow_constructible<_error_type, U>::value)
|
||||
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, basic_result_storage<T, U, V> &&o) noexcept(
|
||||
detail::is_nothrow_constructible<_value_type, T> &&detail::is_nothrow_constructible<_error_type, U>)
|
||||
: _state(static_cast<decltype(o._state) &&>(o._state))
|
||||
, _error(static_cast<U &&>(o._error))
|
||||
{
|
||||
}
|
||||
template <class T, class V>
|
||||
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, basic_result_storage<T, void, V> &&o) noexcept(std::is_nothrow_constructible<_value_type, T>::value)
|
||||
: _state(static_cast<decltype(o._state) &&>(o._state))
|
||||
, _error(_error_type{})
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Neither value nor error type can throw during swap
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
template <> struct basic_result_storage_swap<false, false>
|
||||
#else
|
||||
template <bool value_throws, bool error_throws> struct basic_result_storage_swap
|
||||
#endif
|
||||
{
|
||||
template <class R, class EC, class NoValuePolicy> constexpr basic_result_storage_swap(basic_result_storage<R, EC, NoValuePolicy> &a, basic_result_storage<R, EC, NoValuePolicy> &b)
|
||||
struct make_error_code_compatible_conversion_tag
|
||||
{
|
||||
};
|
||||
template <class T, class U, class V>
|
||||
constexpr basic_result_storage(make_error_code_compatible_conversion_tag /*unused*/, const basic_result_storage<T, U, V> &o) noexcept(
|
||||
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_error_code(std::declval<U>())))
|
||||
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, o._state._value) :
|
||||
_state_type(in_place_type<_error_type>, make_error_code(o._state._error)))
|
||||
{
|
||||
}
|
||||
template <class T, class U, class V>
|
||||
constexpr basic_result_storage(make_error_code_compatible_conversion_tag /*unused*/, basic_result_storage<T, U, V> &&o) noexcept(
|
||||
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_error_code(std::declval<U>())))
|
||||
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, static_cast<T &&>(o._state._value)) :
|
||||
_state_type(in_place_type<_error_type>, make_error_code(static_cast<U &&>(o._state._error))))
|
||||
{
|
||||
}
|
||||
|
||||
struct make_exception_ptr_compatible_conversion_tag
|
||||
{
|
||||
};
|
||||
template <class T, class U, class V>
|
||||
constexpr basic_result_storage(make_exception_ptr_compatible_conversion_tag /*unused*/, const basic_result_storage<T, U, V> &o) noexcept(
|
||||
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_exception_ptr(std::declval<U>())))
|
||||
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, o._state._value) :
|
||||
_state_type(in_place_type<_error_type>, make_exception_ptr(o._state._error)))
|
||||
{
|
||||
}
|
||||
template <class T, class U, class V>
|
||||
constexpr basic_result_storage(make_exception_ptr_compatible_conversion_tag /*unused*/, basic_result_storage<T, U, V> &&o) noexcept(
|
||||
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_exception_ptr(std::declval<U>())))
|
||||
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, static_cast<T &&>(o._state._value)) :
|
||||
_state_type(in_place_type<_error_type>, make_exception_ptr(static_cast<U &&>(o._state._error))))
|
||||
{
|
||||
using std::swap;
|
||||
a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
|
||||
swap(a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
|
||||
}
|
||||
};
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
// Swap potentially throwing value first
|
||||
template <> struct basic_result_storage_swap<true, false>
|
||||
{
|
||||
template <class R, class EC, class NoValuePolicy> constexpr basic_result_storage_swap(basic_result_storage<R, EC, NoValuePolicy> &a, basic_result_storage<R, EC, NoValuePolicy> &b)
|
||||
{
|
||||
using std::swap;
|
||||
a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
|
||||
swap(a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
|
||||
}
|
||||
};
|
||||
// Swap potentially throwing error first
|
||||
template <> struct basic_result_storage_swap<false, true>
|
||||
{
|
||||
template <class R, class EC, class NoValuePolicy> constexpr basic_result_storage_swap(basic_result_storage<R, EC, NoValuePolicy> &a, basic_result_storage<R, EC, NoValuePolicy> &b)
|
||||
{
|
||||
using std::swap;
|
||||
swap(a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
|
||||
a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
|
||||
}
|
||||
};
|
||||
// Both could throw
|
||||
template <> struct basic_result_storage_swap<true, true>
|
||||
{
|
||||
template <class R, class EC, class NoValuePolicy> basic_result_storage_swap(basic_result_storage<R, EC, NoValuePolicy> &a, basic_result_storage<R, EC, NoValuePolicy> &b)
|
||||
{
|
||||
using std::swap;
|
||||
// Swap value and status first, if it throws, status will remain unchanged
|
||||
a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
|
||||
try
|
||||
{
|
||||
swap(a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// First try to put the value and status back
|
||||
try
|
||||
{
|
||||
a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
|
||||
// If that succeeded, continue by rethrowing the exception
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// We are now trapped. The value swapped, the error did not,
|
||||
// trying to restore the value failed. We now have
|
||||
// inconsistent result objects. Best we can do is fix up the
|
||||
// status bits to prevent has_value() == has_error().
|
||||
auto check = [](basic_result_storage<R, EC, NoValuePolicy> &x) {
|
||||
bool has_value = (x._state._status & detail::status_have_value) != 0;
|
||||
bool has_error = (x._state._status & detail::status_have_error) != 0;
|
||||
bool has_exception = (x._state._status & detail::status_have_exception) != 0;
|
||||
if(has_value == (has_error || has_exception))
|
||||
{
|
||||
if(has_value)
|
||||
{
|
||||
// We know the value swapped and is now set, so clear error and exception
|
||||
x._state._status &= ~(detail::status_have_error | detail::status_have_exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We know the value swapped and is now unset, so set error
|
||||
x._state._status |= detail::status_have_error;
|
||||
// TODO: Should I default construct reset _error? It's guaranteed default constructible.
|
||||
}
|
||||
}
|
||||
};
|
||||
check(a);
|
||||
check(b);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Value observers for a very simple basic_result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
594
linx64/include/boost/outcome/detail/coroutine_support.ipp
Normal file
594
linx64/include/boost/outcome/detail/coroutine_support.ipp
Normal file
@@ -0,0 +1,594 @@
|
||||
/* Tells C++ coroutines about Outcome's result
|
||||
(C) 2019-2023 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
|
||||
File Created: Oct 2019
|
||||
|
||||
|
||||
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_COROUTINE_SUPPORT_NAMESPACE_BEGIN
|
||||
#error This header must only be included by outcome/coroutine_support.hpp or outcome/experimental/coroutine_support.hpp
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_DETAIL_COROUTINE_SUPPORT_HPP
|
||||
#define BOOST_OUTCOME_DETAIL_COROUTINE_SUPPORT_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
|
||||
#ifndef BOOST_OUTCOME_COROUTINE_HEADER_TYPE
|
||||
#if __has_include(<coroutine>)
|
||||
#define BOOST_OUTCOME_COROUTINE_HEADER_TYPE 1
|
||||
#elif __has_include(<experimental/coroutine>)
|
||||
#define BOOST_OUTCOME_COROUTINE_HEADER_TYPE 2
|
||||
#else
|
||||
#define BOOST_OUTCOME_COROUTINE_HEADER_TYPE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BOOST_OUTCOME_COROUTINE_HEADER_TYPE && (__cpp_impl_coroutine || (defined(_MSC_VER) && __cpp_coroutines))
|
||||
#ifndef BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_coro_noop) || (!defined(__clang__) && __GNUC__ >= 10)
|
||||
#define BOOST_OUTCOME_HAVE_NOOP_COROUTINE 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
#if _MSC_VER >= 1928 || (!defined(__clang__) && __GNUC__ >= 10)
|
||||
#define BOOST_OUTCOME_HAVE_NOOP_COROUTINE 1
|
||||
#else
|
||||
#define BOOST_OUTCOME_HAVE_NOOP_COROUTINE 0
|
||||
#endif
|
||||
#endif
|
||||
#if BOOST_OUTCOME_COROUTINE_HEADER_TYPE == 1
|
||||
#include <coroutine>
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
namespace awaitables
|
||||
{
|
||||
template <class Promise = void> using coroutine_handle = std::coroutine_handle<Promise>;
|
||||
template <class... Args> using coroutine_traits = std::coroutine_traits<Args...>;
|
||||
using std::suspend_always;
|
||||
using std::suspend_never;
|
||||
#if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
using std::noop_coroutine;
|
||||
#endif
|
||||
} // namespace awaitables
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
#define BOOST_OUTCOME_FOUND_COROUTINE_HEADER 1
|
||||
#elif BOOST_OUTCOME_COROUTINE_HEADER_TYPE == 2
|
||||
#include <experimental/coroutine>
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
namespace awaitables
|
||||
{
|
||||
template <class Promise = void> using coroutine_handle = std::experimental::coroutine_handle<Promise>;
|
||||
template <class... Args> using coroutine_traits = std::experimental::coroutine_traits<Args...>;
|
||||
using std::experimental::suspend_always;
|
||||
using std::experimental::suspend_never;
|
||||
#if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
using std::experimental::noop_coroutine;
|
||||
#endif
|
||||
} // namespace awaitables
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
#define BOOST_OUTCOME_FOUND_COROUTINE_HEADER 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
namespace awaitables
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct error_type_not_found
|
||||
{
|
||||
};
|
||||
struct exception_type_not_found
|
||||
{
|
||||
};
|
||||
template <class T> struct type_found
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
template <class T, class U = typename T::error_type> constexpr inline type_found<U> extract_error_type(int /*unused*/) { return {}; }
|
||||
template <class T> constexpr inline type_found<error_type_not_found> extract_error_type(...) { return {}; }
|
||||
template <class T, class U = typename T::exception_type> constexpr inline type_found<U> extract_exception_type(int /*unused*/) { return {}; }
|
||||
template <class T> constexpr inline type_found<exception_type_not_found> extract_exception_type(...) { return {}; }
|
||||
|
||||
BOOST_OUTCOME_TEMPLATE(class T, class U)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(BOOST_OUTCOME_V2_NAMESPACE::detail::is_constructible<U, T>))
|
||||
inline bool try_set_error(T &&e, U *result)
|
||||
{
|
||||
new(result) U(static_cast<T &&>(e));
|
||||
return true;
|
||||
}
|
||||
template <class T> inline bool try_set_error(T && /*unused*/, ...) { return false; }
|
||||
BOOST_OUTCOME_TEMPLATE(class T, class U)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(BOOST_OUTCOME_V2_NAMESPACE::detail::is_constructible<U, T>))
|
||||
inline void set_or_rethrow(T &e, U *result) { new(result) U(e); }
|
||||
template <class T> inline void set_or_rethrow(T &e, ...) { rethrow_exception(e); }
|
||||
template <class T> class fake_atomic
|
||||
{
|
||||
T _v;
|
||||
|
||||
public:
|
||||
constexpr fake_atomic(T v)
|
||||
: _v(v)
|
||||
{
|
||||
}
|
||||
T load(std::memory_order /*unused*/) { return _v; }
|
||||
void store(T v, std::memory_order /*unused*/) { _v = v; }
|
||||
};
|
||||
|
||||
#ifdef BOOST_OUTCOME_FOUND_COROUTINE_HEADER
|
||||
template <class Awaitable, bool suspend_initial, bool use_atomic, bool is_void> struct outcome_promise_type
|
||||
{
|
||||
using container_type = typename Awaitable::container_type;
|
||||
using result_set_type = std::conditional_t<use_atomic, std::atomic<bool>, fake_atomic<bool>>;
|
||||
union
|
||||
{
|
||||
BOOST_OUTCOME_V2_NAMESPACE::detail::empty_type _default{};
|
||||
container_type result;
|
||||
};
|
||||
result_set_type result_set{false};
|
||||
coroutine_handle<> continuation;
|
||||
|
||||
outcome_promise_type() noexcept {}
|
||||
outcome_promise_type(const outcome_promise_type &) = delete;
|
||||
outcome_promise_type(outcome_promise_type &&) = delete;
|
||||
outcome_promise_type &operator=(const outcome_promise_type &) = delete;
|
||||
outcome_promise_type &operator=(outcome_promise_type &&) = delete;
|
||||
~outcome_promise_type()
|
||||
{
|
||||
if(result_set.load(std::memory_order_acquire))
|
||||
{
|
||||
result.~container_type(); // could throw
|
||||
}
|
||||
}
|
||||
auto get_return_object()
|
||||
{
|
||||
return Awaitable{*this}; // could throw bad_alloc
|
||||
}
|
||||
void return_value(container_type &&value)
|
||||
{
|
||||
assert(!result_set.load(std::memory_order_acquire));
|
||||
if(result_set.load(std::memory_order_acquire))
|
||||
{
|
||||
result.~container_type(); // could throw
|
||||
}
|
||||
new(&result) container_type(static_cast<container_type &&>(value)); // could throw
|
||||
result_set.store(true, std::memory_order_release);
|
||||
}
|
||||
void return_value(const container_type &value)
|
||||
{
|
||||
assert(!result_set.load(std::memory_order_acquire));
|
||||
if(result_set.load(std::memory_order_acquire))
|
||||
{
|
||||
result.~container_type(); // could throw
|
||||
}
|
||||
new(&result) container_type(value); // could throw
|
||||
result_set.store(true, std::memory_order_release);
|
||||
}
|
||||
void unhandled_exception()
|
||||
{
|
||||
assert(!result_set.load(std::memory_order_acquire));
|
||||
if(result_set.load(std::memory_order_acquire))
|
||||
{
|
||||
result.~container_type();
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
auto e = std::current_exception();
|
||||
auto ec = detail::error_from_exception(static_cast<decltype(e) &&>(e), {});
|
||||
// Try to set error code first
|
||||
if(!detail::error_is_set(ec) || !detail::try_set_error(static_cast<decltype(ec) &&>(ec), &result))
|
||||
{
|
||||
detail::set_or_rethrow(e, &result); // could throw
|
||||
}
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
result_set.store(true, std::memory_order_release);
|
||||
}
|
||||
auto initial_suspend() noexcept
|
||||
{
|
||||
struct awaiter
|
||||
{
|
||||
bool await_ready() noexcept { return !suspend_initial; }
|
||||
void await_resume() noexcept {}
|
||||
void await_suspend(coroutine_handle<> /*unused*/) noexcept {}
|
||||
};
|
||||
return awaiter{};
|
||||
}
|
||||
auto final_suspend() noexcept
|
||||
{
|
||||
struct awaiter
|
||||
{
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_resume() noexcept {}
|
||||
#if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
coroutine_handle<> await_suspend(coroutine_handle<outcome_promise_type> self) noexcept
|
||||
{
|
||||
return self.promise().continuation ? self.promise().continuation : noop_coroutine();
|
||||
}
|
||||
#else
|
||||
void await_suspend(coroutine_handle<outcome_promise_type> self)
|
||||
{
|
||||
if(self.promise().continuation)
|
||||
{
|
||||
return self.promise().continuation.resume();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
return awaiter{};
|
||||
}
|
||||
};
|
||||
template <class Awaitable, bool suspend_initial, bool use_atomic> struct outcome_promise_type<Awaitable, suspend_initial, use_atomic, true>
|
||||
{
|
||||
using container_type = void;
|
||||
using result_set_type = std::conditional_t<use_atomic, std::atomic<bool>, fake_atomic<bool>>;
|
||||
result_set_type result_set{false};
|
||||
coroutine_handle<> continuation;
|
||||
|
||||
outcome_promise_type() {}
|
||||
outcome_promise_type(const outcome_promise_type &) = delete;
|
||||
outcome_promise_type(outcome_promise_type &&) = delete;
|
||||
outcome_promise_type &operator=(const outcome_promise_type &) = delete;
|
||||
outcome_promise_type &operator=(outcome_promise_type &&) = delete;
|
||||
~outcome_promise_type() = default;
|
||||
auto get_return_object()
|
||||
{
|
||||
return Awaitable{*this}; // could throw bad_alloc
|
||||
}
|
||||
void return_void() noexcept
|
||||
{
|
||||
assert(!result_set.load(std::memory_order_acquire));
|
||||
result_set.store(true, std::memory_order_release);
|
||||
}
|
||||
void unhandled_exception()
|
||||
{
|
||||
assert(!result_set.load(std::memory_order_acquire));
|
||||
std::rethrow_exception(std::current_exception()); // throws
|
||||
}
|
||||
auto initial_suspend() noexcept
|
||||
{
|
||||
struct awaiter
|
||||
{
|
||||
bool await_ready() noexcept { return !suspend_initial; }
|
||||
void await_resume() noexcept {}
|
||||
void await_suspend(coroutine_handle<> /*unused*/) noexcept {}
|
||||
};
|
||||
return awaiter{};
|
||||
}
|
||||
auto final_suspend() noexcept
|
||||
{
|
||||
struct awaiter
|
||||
{
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_resume() noexcept {}
|
||||
#if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
coroutine_handle<> await_suspend(coroutine_handle<outcome_promise_type> self) noexcept
|
||||
{
|
||||
return self.promise().continuation ? self.promise().continuation : noop_coroutine();
|
||||
}
|
||||
#else
|
||||
void await_suspend(coroutine_handle<outcome_promise_type> self)
|
||||
{
|
||||
if(self.promise().continuation)
|
||||
{
|
||||
return self.promise().continuation.resume();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
return awaiter{};
|
||||
}
|
||||
};
|
||||
template <class Awaitable, bool suspend_initial, bool use_atomic>
|
||||
constexpr inline auto move_result_from_promise_if_not_void(outcome_promise_type<Awaitable, suspend_initial, use_atomic, false> &p)
|
||||
{
|
||||
return static_cast<typename Awaitable::container_type &&>(p.result);
|
||||
}
|
||||
template <class Awaitable, bool suspend_initial, bool use_atomic>
|
||||
constexpr inline void move_result_from_promise_if_not_void(outcome_promise_type<Awaitable, suspend_initial, use_atomic, true> & /*unused*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Cont, class Executor, bool suspend_initial, bool use_atomic> struct BOOST_OUTCOME_NODISCARD awaitable
|
||||
{
|
||||
using container_type = Cont;
|
||||
using value_type = Cont;
|
||||
using executor_type = Executor;
|
||||
using promise_type = outcome_promise_type<awaitable, suspend_initial, use_atomic, std::is_void<container_type>::value>;
|
||||
coroutine_handle<promise_type> _h;
|
||||
|
||||
awaitable(awaitable &&o) noexcept
|
||||
: _h(static_cast<coroutine_handle<promise_type> &&>(o._h))
|
||||
{
|
||||
o._h = nullptr;
|
||||
}
|
||||
awaitable(const awaitable &o) = delete;
|
||||
awaitable &operator=(awaitable &&) = delete; // as per P1056
|
||||
awaitable &operator=(const awaitable &) = delete;
|
||||
~awaitable()
|
||||
{
|
||||
if(_h)
|
||||
{
|
||||
_h.destroy();
|
||||
}
|
||||
}
|
||||
explicit awaitable(promise_type &p) // could throw
|
||||
: _h(coroutine_handle<promise_type>::from_promise(p))
|
||||
{
|
||||
}
|
||||
bool valid() const noexcept { return _h != nullptr; }
|
||||
bool await_ready() noexcept { return _h.promise().result_set.load(std::memory_order_acquire); }
|
||||
container_type await_resume()
|
||||
{
|
||||
assert(_h.promise().result_set.load(std::memory_order_acquire));
|
||||
if(!_h.promise().result_set.load(std::memory_order_acquire))
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
return detail::move_result_from_promise_if_not_void(_h.promise());
|
||||
}
|
||||
#if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
coroutine_handle<> await_suspend(coroutine_handle<> cont) noexcept
|
||||
{
|
||||
_h.promise().continuation = cont;
|
||||
return _h;
|
||||
}
|
||||
#else
|
||||
void await_suspend(coroutine_handle<> cont)
|
||||
{
|
||||
_h.promise().continuation = cont;
|
||||
_h.resume();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class ContType, class Executor, bool suspend_initial, bool use_atomic> struct generator
|
||||
{
|
||||
using container_type = ContType;
|
||||
using value_type = ContType;
|
||||
using executor_type = Executor;
|
||||
class promise_type
|
||||
{
|
||||
friend struct generator;
|
||||
using result_set_type = std::conditional_t<use_atomic, std::atomic<int8_t>, fake_atomic<int8_t>>;
|
||||
union
|
||||
{
|
||||
BOOST_OUTCOME_V2_NAMESPACE::detail::empty_type _default{};
|
||||
container_type result;
|
||||
};
|
||||
result_set_type result_set{0};
|
||||
coroutine_handle<> continuation;
|
||||
|
||||
public:
|
||||
promise_type() {}
|
||||
promise_type(const promise_type &) = delete;
|
||||
promise_type(promise_type &&) = delete;
|
||||
promise_type &operator=(const promise_type &) = delete;
|
||||
promise_type &operator=(promise_type &&) = delete;
|
||||
~promise_type()
|
||||
{
|
||||
if(result_set.load(std::memory_order_acquire) == 1)
|
||||
{
|
||||
result.~container_type(); // could throw
|
||||
}
|
||||
}
|
||||
|
||||
auto get_return_object()
|
||||
{
|
||||
return generator{*this}; // could throw bad_alloc
|
||||
}
|
||||
void return_void() noexcept
|
||||
{
|
||||
assert(result_set.load(std::memory_order_acquire) >= 0);
|
||||
if(result_set.load(std::memory_order_acquire) == 1)
|
||||
{
|
||||
result.~container_type(); // could throw
|
||||
}
|
||||
result_set.store(-1, std::memory_order_release);
|
||||
}
|
||||
suspend_always yield_value(container_type &&value)
|
||||
{
|
||||
assert(result_set.load(std::memory_order_acquire) >= 0);
|
||||
if(result_set.load(std::memory_order_acquire) == 1)
|
||||
{
|
||||
result.~container_type(); // could throw
|
||||
}
|
||||
new(&result) container_type(static_cast<container_type &&>(value)); // could throw
|
||||
result_set.store(1, std::memory_order_release);
|
||||
return {};
|
||||
}
|
||||
suspend_always yield_value(const container_type &value)
|
||||
{
|
||||
assert(result_set.load(std::memory_order_acquire) >= 0);
|
||||
if(result_set.load(std::memory_order_acquire) == 1)
|
||||
{
|
||||
result.~container_type(); // could throw
|
||||
}
|
||||
new(&result) container_type(value); // could throw
|
||||
result_set.store(1, std::memory_order_release);
|
||||
return {};
|
||||
}
|
||||
void unhandled_exception()
|
||||
{
|
||||
assert(result_set.load(std::memory_order_acquire) >= 0);
|
||||
if(result_set.load(std::memory_order_acquire) == 1)
|
||||
{
|
||||
result.~container_type();
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
auto e = std::current_exception();
|
||||
auto ec = detail::error_from_exception(static_cast<decltype(e) &&>(e), {});
|
||||
// Try to set error code first
|
||||
if(!detail::error_is_set(ec) || !detail::try_set_error(static_cast<decltype(ec) &&>(ec), &result))
|
||||
{
|
||||
detail::set_or_rethrow(e, &result); // could throw
|
||||
}
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
result_set.store(1, std::memory_order_release);
|
||||
}
|
||||
auto initial_suspend() noexcept
|
||||
{
|
||||
struct awaiter
|
||||
{
|
||||
bool await_ready() noexcept { return !suspend_initial; }
|
||||
void await_resume() noexcept {}
|
||||
void await_suspend(coroutine_handle<> /*unused*/) noexcept {}
|
||||
};
|
||||
return awaiter{};
|
||||
}
|
||||
auto final_suspend() noexcept
|
||||
{
|
||||
struct awaiter
|
||||
{
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_resume() noexcept {}
|
||||
#if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
coroutine_handle<> await_suspend(coroutine_handle<promise_type> self) noexcept
|
||||
{
|
||||
return self.promise().continuation ? self.promise().continuation : noop_coroutine();
|
||||
}
|
||||
#else
|
||||
void await_suspend(coroutine_handle<promise_type> self)
|
||||
{
|
||||
if(self.promise().continuation)
|
||||
{
|
||||
return self.promise().continuation.resume();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
return awaiter{};
|
||||
}
|
||||
};
|
||||
coroutine_handle<promise_type> _h;
|
||||
|
||||
generator(generator &&o) noexcept
|
||||
: _h(static_cast<coroutine_handle<promise_type> &&>(o._h))
|
||||
{
|
||||
o._h = nullptr;
|
||||
}
|
||||
generator(const generator &o) = delete;
|
||||
generator &operator=(generator &&) = delete; // as per P1056
|
||||
generator &operator=(const generator &) = delete;
|
||||
~generator()
|
||||
{
|
||||
if(_h)
|
||||
{
|
||||
_h.destroy();
|
||||
}
|
||||
}
|
||||
explicit generator(promise_type &p) // could throw
|
||||
: _h(coroutine_handle<promise_type>::from_promise(p))
|
||||
{
|
||||
}
|
||||
explicit operator bool() const // could throw
|
||||
{
|
||||
return valid();
|
||||
}
|
||||
bool valid() const // could throw
|
||||
{
|
||||
auto &p = _h.promise();
|
||||
if(p.result_set.load(std::memory_order_acquire) == 0)
|
||||
{
|
||||
const_cast<generator *>(this)->_h();
|
||||
}
|
||||
return p.result_set.load(std::memory_order_acquire) >= 0;
|
||||
}
|
||||
container_type operator()() // could throw
|
||||
{
|
||||
auto &p = _h.promise();
|
||||
if(p.result_set.load(std::memory_order_acquire) == 0)
|
||||
{
|
||||
_h();
|
||||
}
|
||||
assert(p.result_set.load(std::memory_order_acquire) >= 0);
|
||||
if(p.result_set.load(std::memory_order_acquire) < 0)
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
container_type ret(static_cast<container_type &&>(p.result));
|
||||
p.result.~container_type(); // could throw
|
||||
p.result_set.store(0, std::memory_order_release);
|
||||
return ret;
|
||||
}
|
||||
#if BOOST_OUTCOME_HAVE_NOOP_COROUTINE
|
||||
coroutine_handle<> await_suspend(coroutine_handle<> cont) noexcept
|
||||
{
|
||||
_h.promise().continuation = cont;
|
||||
return _h;
|
||||
}
|
||||
#else
|
||||
void await_suspend(coroutine_handle<> cont)
|
||||
{
|
||||
_h.promise().continuation = cont;
|
||||
_h.resume();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
} // namespace awaitables
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_OUTCOME_FOUND_COROUTINE_HEADER
|
||||
BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_EXPORT_BEGIN
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class Executor = void> using eager = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, false, false>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class Executor = void> using atomic_eager = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, false, true>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class Executor = void> using lazy = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, true, false>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class Executor = void> using atomic_lazy = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::awaitable<T, Executor, true, true>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class Executor = void> using generator = BOOST_OUTCOME_V2_NAMESPACE::awaitables::detail::generator<T, Executor, true, false>;
|
||||
|
||||
BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_END
|
||||
#endif
|
||||
33
linx64/include/boost/outcome/detail/revision.hpp
Normal file
33
linx64/include/boost/outcome/detail/revision.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* UPDATED BY SCRIPT
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (225 commits)
|
||||
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
|
||||
#define BOOST_OUTCOME_PREVIOUS_COMMIT_REF d45173e172a9884022ec5795e7f9fc9096d4edd2
|
||||
#define BOOST_OUTCOME_PREVIOUS_COMMIT_DATE "2023-07-20 08:44:04 +00:00"
|
||||
#define BOOST_OUTCOME_PREVIOUS_COMMIT_UNIQUE d45173e1
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Traits for Outcome
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
|
||||
File Created: March 2018
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace detail
|
||||
#endif
|
||||
)
|
||||
{
|
||||
state._status |= status_error_is_errno;
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
}
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const std::error_condition &error)
|
||||
@@ -59,10 +59,12 @@ namespace detail
|
||||
#endif
|
||||
)
|
||||
{
|
||||
state._status |= status_error_is_errno;
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
}
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const std::errc & /*unused*/) { state._status |= status_error_is_errno; }
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const std::errc & /*unused*/) {
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -105,6 +107,7 @@ namespace trait
|
||||
{
|
||||
// Shortcut this for lower build impact
|
||||
static constexpr bool value = true;
|
||||
using type = std::error_code;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Traits for Outcome
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (3 commits)
|
||||
File Created: March 2018
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace trait
|
||||
template <> struct _is_exception_ptr_available<std::exception_ptr>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
using type = std::exception_ptr;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
42
linx64/include/boost/outcome/detail/version.hpp
Normal file
42
linx64/include/boost/outcome/detail/version.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Sets Outcome version
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
|
||||
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_MAJOR 2
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_MINOR 2
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_PATCH 3
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_REVISION 0 // Revision version for cmake and DLL version stamping
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#ifdef BOOST_OUTCOME_ENABLE_ABI_PERMUTATION
|
||||
#define BOOST_OUTCOME_UNSTABLE_VERSION
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/* Tells C++ coroutines about Outcome's result
|
||||
(C) 2019-2023 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
|
||||
File Created: Oct 2019
|
||||
|
||||
|
||||
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_EXPERIMENTAL_COROUTINE_SUPPORT_HPP
|
||||
#define BOOST_OUTCOME_EXPERIMENTAL_COROUTINE_SUPPORT_HPP
|
||||
|
||||
#include "../config.hpp"
|
||||
|
||||
#define BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_BEGIN \
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN namespace experimental \
|
||||
{ \
|
||||
namespace awaitables \
|
||||
{
|
||||
//
|
||||
#define BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_EXPORT_BEGIN \
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN namespace experimental \
|
||||
{ \
|
||||
namespace awaitables \
|
||||
{
|
||||
//
|
||||
#define BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_END \
|
||||
} \
|
||||
} \
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#if !BOOST_OUTCOME_USE_SYSTEM_STATUS_CODE && __has_include("status-code/status-code/system_code_from_exception.hpp")
|
||||
#include "status-code/status-code/system_code_from_exception.hpp"
|
||||
#else
|
||||
#include <status-code/system_code_from_exception.hpp>
|
||||
#endif
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
namespace awaitables
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline bool error_is_set(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code &sc) noexcept { return sc.failure(); }
|
||||
inline BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code error_from_exception(std::exception_ptr &&ep = std::current_exception(), BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code not_matched = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::generic_code(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc::resource_unavailable_try_again)) noexcept
|
||||
{
|
||||
return BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code_from_exception(static_cast<std::exception_ptr &&>(ep), static_cast<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::system_code &&>(not_matched));
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace awaitables
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
#include "../detail/coroutine_support.ipp"
|
||||
|
||||
#undef BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_BEGIN
|
||||
#undef BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_EXPORT_BEGIN
|
||||
#undef BOOST_OUTCOME_COROUTINE_SUPPORT_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* C interface for result
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
|
||||
File Created: Aug 2017
|
||||
|
||||
|
||||
@@ -33,12 +33,20 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <stdint.h> // for intptr_t
|
||||
|
||||
#define BOOST_OUTCOME_C_DECLARE_RESULT(ident, R, S) \
|
||||
struct cxx_result_##ident \
|
||||
{ \
|
||||
R value; \
|
||||
unsigned flags; \
|
||||
S error; \
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define BOOST_OUTCOME_C_DECLARE_RESULT(ident, R, S) \
|
||||
struct cxx_result_##ident \
|
||||
{ \
|
||||
union \
|
||||
{ \
|
||||
R value; \
|
||||
S error; \
|
||||
}; \
|
||||
unsigned flags; \
|
||||
}
|
||||
|
||||
#define BOOST_OUTCOME_C_RESULT(ident) struct cxx_result_##ident
|
||||
@@ -51,32 +59,46 @@ DEALINGS IN THE SOFTWARE.
|
||||
#define BOOST_OUTCOME_C_RESULT_ERROR_IS_ERRNO(r) (((r).flags & (1U << 4U)) == (1U << 4U))
|
||||
|
||||
|
||||
/***************************** <system_error2> support ******************************/
|
||||
/***************************** <system_error2> support ******************************/
|
||||
|
||||
#define BOOST_OUTCOME_C_DECLARE_STATUS_CODE(ident, value_type) \
|
||||
struct cxx_status_code_##ident \
|
||||
{ \
|
||||
void *domain; \
|
||||
value_type value; \
|
||||
#define BOOST_OUTCOME_C_DECLARE_STATUS_CODE(ident, value_type) \
|
||||
struct cxx_status_code_##ident \
|
||||
{ \
|
||||
void *domain; \
|
||||
value_type value; \
|
||||
};
|
||||
|
||||
#define BOOST_OUTCOME_C_STATUS_CODE(ident) struct cxx_status_code_##ident
|
||||
|
||||
#define BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE(ident, R, S) \
|
||||
struct cxx_result_status_code_##ident \
|
||||
{ \
|
||||
R value; \
|
||||
unsigned flags; \
|
||||
S error; \
|
||||
}
|
||||
|
||||
struct cxx_status_code_posix
|
||||
{
|
||||
void *domain;
|
||||
int value;
|
||||
};
|
||||
#define BOOST_OUTCOME_C_DECLARE_RESULT_ERRNO(ident, R) BOOST_OUTCOME_C_DECLARE_RESULT(posix_##ident, R, struct cxx_status_code_posix)
|
||||
#define BOOST_OUTCOME_C_RESULT_ERRNO(ident) BOOST_OUTCOME_C_RESULT(posix_##ident)
|
||||
#define BOOST_OUTCOME_C_RESULT_STATUS_CODE(ident) struct cxx_result_status_code_##ident
|
||||
|
||||
struct cxx_status_code_system
|
||||
{
|
||||
void *domain;
|
||||
intptr_t value;
|
||||
};
|
||||
#define BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM(ident, R) BOOST_OUTCOME_C_DECLARE_RESULT(system_##ident, R, struct cxx_status_code_system)
|
||||
#define BOOST_OUTCOME_C_RESULT_SYSTEM(ident) BOOST_OUTCOME_C_RESULT(system_##ident)
|
||||
|
||||
struct cxx_status_code_posix
|
||||
{
|
||||
void *domain;
|
||||
int value;
|
||||
};
|
||||
#define BOOST_OUTCOME_C_DECLARE_RESULT_ERRNO(ident, R) BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE(posix_##ident, R, struct cxx_status_code_posix)
|
||||
#define BOOST_OUTCOME_C_RESULT_ERRNO(ident) BOOST_OUTCOME_C_RESULT_STATUS_CODE(posix_##ident)
|
||||
|
||||
struct cxx_status_code_system
|
||||
{
|
||||
void *domain;
|
||||
intptr_t value;
|
||||
};
|
||||
#define BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM(ident, R) BOOST_OUTCOME_C_DECLARE_RESULT_STATUS_CODE(system_##ident, R, struct cxx_status_code_system)
|
||||
#define BOOST_OUTCOME_C_RESULT_SYSTEM(ident) BOOST_OUTCOME_C_RESULT_STATUS_CODE(system_##ident)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_CONFIG_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONFIG_HPP
|
||||
|
||||
// < 0.1 each
|
||||
#include <cassert>
|
||||
#include <cstddef> // for size_t
|
||||
#include <cstdlib> // for free
|
||||
|
||||
// 0.22
|
||||
#include <type_traits>
|
||||
|
||||
// 0.29
|
||||
#include <atomic>
|
||||
|
||||
// 0.28 (0.15 of which is exception_ptr)
|
||||
#include <exception> // for std::exception
|
||||
// <new> includes <exception>, <exception> includes <new>
|
||||
#include <new>
|
||||
|
||||
// 0.01
|
||||
#include <initializer_list>
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
|
||||
//! Defined to be `constexpr` when on C++ 14 or better compilers. Usually automatic, can be overriden.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 constexpr
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN [[noreturn]]
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN)
|
||||
#ifdef __has_cpp_attribute
|
||||
#if __has_cpp_attribute(noreturn)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN [[noreturn]]
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN)
|
||||
#if defined(_MSC_VER)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN __declspec(noreturn)
|
||||
#elif defined(__GNUC__)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN __attribute__((__noreturn__))
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#endif
|
||||
#endif
|
||||
// GCCs before 7 don't grok [[noreturn]] virtual functions, and warn annoyingly
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 7
|
||||
#undef BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD [[nodiscard]]
|
||||
#endif
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#ifdef __has_cpp_attribute
|
||||
#if __has_cpp_attribute(nodiscard)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD [[nodiscard]]
|
||||
#endif
|
||||
#elif defined(__clang__)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD __attribute__((warn_unused_result))
|
||||
#elif defined(_MSC_VER)
|
||||
// _Must_inspect_result_ expands into this
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD \
|
||||
__declspec("SAL_name" \
|
||||
"(" \
|
||||
"\"_Must_inspect_result_\"" \
|
||||
"," \
|
||||
"\"\"" \
|
||||
"," \
|
||||
"\"2\"" \
|
||||
")") __declspec("SAL_begin") __declspec("SAL_post") __declspec("SAL_mustInspect") __declspec("SAL_post") __declspec("SAL_checkReturn") __declspec("SAL_end")
|
||||
#endif
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE
|
||||
//! The system_error2 namespace name.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE system_error2
|
||||
//! Begins the system_error2 namespace.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN \
|
||||
namespace system_error2 \
|
||||
{
|
||||
//! Ends the system_error2 namespace.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END }
|
||||
#endif
|
||||
|
||||
//! Namespace for the library
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
//! Namespace for user specialised traits
|
||||
namespace traits
|
||||
{
|
||||
/*! Specialise to true if you guarantee that a type is move relocating (i.e.
|
||||
its move constructor equals copying bits from old to new, old is left in a
|
||||
default constructed state, and calling the destructor on a default constructed
|
||||
instance is trivial). All trivially copyable types are move relocating by
|
||||
definition, and that is the unspecialised implementation.
|
||||
*/
|
||||
template <class T> struct is_move_relocating
|
||||
{
|
||||
static constexpr bool value = std::is_trivially_copyable<T>::value;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 size_t cstrlen(const char *str)
|
||||
{
|
||||
const char *end = nullptr;
|
||||
for(end = str; *end != 0; ++end) // NOLINT
|
||||
;
|
||||
return end - str;
|
||||
}
|
||||
|
||||
/* A partially compliant implementation of C++20's std::bit_cast function contributed
|
||||
by Jesse Towner. TODO FIXME Replace with C++ 20 bit_cast when available.
|
||||
|
||||
Our bit_cast is only guaranteed to be constexpr when both the input and output
|
||||
arguments are either integrals or enums. However, this covers most use cases
|
||||
since the vast majority of status_codes have an underlying type that is either
|
||||
an integral or enum.
|
||||
*/
|
||||
|
||||
template <class T> using is_integral_or_enum = std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value>;
|
||||
|
||||
template <class To, class From> using is_static_castable = std::integral_constant<bool, is_integral_or_enum<To>::value && is_integral_or_enum<From>::value>;
|
||||
|
||||
template <class To, class From> using is_bit_castable = std::integral_constant<bool, sizeof(To) == sizeof(From) && traits::is_move_relocating<To>::value && traits::is_move_relocating<From>::value>;
|
||||
|
||||
template <class To, class From> union bit_cast_union {
|
||||
From source;
|
||||
To target;
|
||||
};
|
||||
|
||||
template <class To, class From, typename std::enable_if<is_bit_castable<To, From>::value && is_static_castable<To, From>::value, bool>::type = true> constexpr To bit_cast(const From &from) noexcept { return static_cast<To>(from); }
|
||||
|
||||
template <class To, class From, typename std::enable_if<is_bit_castable<To, From>::value && !is_static_castable<To, From>::value, bool>::type = true> constexpr To bit_cast(const From &from) noexcept { return bit_cast_union<To, From>{from}.target; }
|
||||
|
||||
/* erasure_cast performs a bit_cast with additional rules to handle types
|
||||
of differing sizes. For integral & enum types, it may perform a narrowing
|
||||
or widing conversion with static_cast if necessary, before doing the final
|
||||
conversion with bit_cast. When casting to or from non-integral, non-enum
|
||||
types it may insert the value into another object with extra padding bytes
|
||||
to satisfy bit_cast's preconditions that both types have the same size. */
|
||||
|
||||
template <class To, class From> using is_erasure_castable = std::integral_constant<bool, traits::is_move_relocating<To>::value && traits::is_move_relocating<From>::value>;
|
||||
|
||||
template <class T, bool = std::is_enum<T>::value> struct identity_or_underlying_type
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
template <class T> struct identity_or_underlying_type<T, true>
|
||||
{
|
||||
using type = typename std::underlying_type<T>::type;
|
||||
};
|
||||
|
||||
template <class OfSize, class OfSign>
|
||||
using erasure_integer_type = typename std::conditional<std::is_signed<typename identity_or_underlying_type<OfSign>::type>::value, typename std::make_signed<typename identity_or_underlying_type<OfSize>::type>::type, typename std::make_unsigned<typename identity_or_underlying_type<OfSize>::type>::type>::type;
|
||||
|
||||
template <class ErasedType, std::size_t N> struct padded_erasure_object
|
||||
{
|
||||
static_assert(traits::is_move_relocating<ErasedType>::value, "ErasedType must be TriviallyCopyable or MoveRelocating");
|
||||
static_assert(alignof(ErasedType) <= sizeof(ErasedType), "ErasedType must not be over-aligned");
|
||||
ErasedType value;
|
||||
char padding[N];
|
||||
constexpr explicit padded_erasure_object(const ErasedType &v) noexcept
|
||||
: value(v)
|
||||
, padding{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && (sizeof(To) == sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(from); }
|
||||
|
||||
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && is_static_castable<To, From>::value && (sizeof(To) < sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept { return static_cast<To>(bit_cast<erasure_integer_type<From, To>>(from)); }
|
||||
|
||||
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && is_static_castable<To, From>::value && (sizeof(To) > sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(static_cast<erasure_integer_type<To, From>>(from)); }
|
||||
|
||||
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) < sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept
|
||||
{
|
||||
return bit_cast<padded_erasure_object<To, sizeof(From) - sizeof(To)>>(from).value;
|
||||
}
|
||||
|
||||
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) > sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept
|
||||
{
|
||||
return bit_cast<To>(padded_erasure_object<From, sizeof(To) - sizeof(From)>{from});
|
||||
}
|
||||
} // namespace detail
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_FATAL
|
||||
#include <cstdlib> // for abort
|
||||
#ifdef __APPLE__
|
||||
#include <unistd.h> // for write
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
{
|
||||
namespace avoid_stdio_include
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
extern "C" ptrdiff_t write(int, const void *, size_t);
|
||||
#endif
|
||||
}
|
||||
inline void do_fatal_exit(const char *msg)
|
||||
{
|
||||
using namespace avoid_stdio_include;
|
||||
write(2 /*stderr*/, msg, cstrlen(msg));
|
||||
write(2 /*stderr*/, "\n", 1);
|
||||
abort();
|
||||
}
|
||||
} // namespace detail
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
//! Prints msg to stderr, and calls `std::terminate()`. Can be overriden via predefinition.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_FATAL(msg) ::BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::detail::do_fatal_exit(msg)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,342 +0,0 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Jun 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_ERRORED_STATUS_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_ERRORED_STATUS_CODE_HPP
|
||||
|
||||
#include "generic_code.hpp"
|
||||
#include "status_code_ptr.hpp"
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
/*! A `status_code` which is always a failure. The closest equivalent to
|
||||
`std::error_code`, except it cannot be modified, and is templated.
|
||||
|
||||
Differences from `status_code`:
|
||||
|
||||
- Never successful (this contract is checked on construction, if fails then it
|
||||
terminates the process).
|
||||
- Is immutable.
|
||||
*/
|
||||
template <class DomainType> class errored_status_code : public status_code<DomainType>
|
||||
{
|
||||
using _base = status_code<DomainType>;
|
||||
using _base::clear;
|
||||
using _base::success;
|
||||
|
||||
void _check()
|
||||
{
|
||||
if(_base::success())
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
//! The type of the erased error code.
|
||||
using typename _base::value_type;
|
||||
//! The type of a reference to a message string.
|
||||
using typename _base::string_ref;
|
||||
|
||||
//! Default constructor.
|
||||
errored_status_code() = default;
|
||||
//! Copy constructor.
|
||||
errored_status_code(const errored_status_code &) = default;
|
||||
//! Move constructor.
|
||||
errored_status_code(errored_status_code &&) = default; // NOLINT
|
||||
//! Copy assignment.
|
||||
errored_status_code &operator=(const errored_status_code &) = default;
|
||||
//! Move assignment.
|
||||
errored_status_code &operator=(errored_status_code &&) = default; // NOLINT
|
||||
~errored_status_code() = default;
|
||||
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(const _base &o) noexcept(std::is_nothrow_copy_constructible<_base>::value)
|
||||
: _base(o)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(_base &&o) noexcept(std::is_nothrow_move_constructible<_base>::value)
|
||||
: _base(static_cast<_base &&>(o))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH STATUS_CODE *****/
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
template <class T, class... Args, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<!std::is_same<typename std::decay<T>::type, errored_status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, in_place_t>::value // not in_place_t
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<errored_status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
|
||||
bool>::type = true>
|
||||
errored_status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: errored_status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit in-place construction.
|
||||
template <class... Args>
|
||||
explicit errored_status_code(in_place_t _, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args &&...>::value)
|
||||
: _base(_, static_cast<Args &&>(args)...)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit in-place construction from initialiser list.
|
||||
template <class T, class... Args>
|
||||
explicit errored_status_code(in_place_t _, std::initializer_list<T> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<T>, Args &&...>::value)
|
||||
: _base(_, il, static_cast<Args &&>(args)...)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit copy construction from a `value_type`.
|
||||
explicit errored_status_code(const value_type &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: _base(v)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit move construction from a `value_type`.
|
||||
explicit errored_status_code(value_type &&v) noexcept(std::is_nothrow_move_constructible<value_type>::value)
|
||||
: _base(static_cast<value_type &&>(v))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
/*! Explicit construction from an erased status code. Available only if
|
||||
`value_type` is trivially destructible and `sizeof(status_code) <= sizeof(status_code<erased<>>)`.
|
||||
Does not check if domains are equal.
|
||||
*/
|
||||
template <class ErasedType, //
|
||||
typename std::enable_if<detail::type_erasure_is_safe<ErasedType, value_type>::value, bool>::type = true>
|
||||
explicit errored_status_code(const status_code<erased<ErasedType>> &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: errored_status_code(detail::erasure_cast<value_type>(v.value())) // NOLINT
|
||||
{
|
||||
assert(v.domain() == this->domain()); // NOLINT
|
||||
_check();
|
||||
}
|
||||
|
||||
//! Return a const reference to the `value_type`.
|
||||
constexpr const value_type &value() const &noexcept { return this->_value; }
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class DomainType> struct is_move_relocating<errored_status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = is_move_relocating<typename DomainType::value_type>::value;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
template <class ErasedType> class errored_status_code<erased<ErasedType>> : public status_code<erased<ErasedType>>
|
||||
{
|
||||
using _base = status_code<erased<ErasedType>>;
|
||||
using _base::success;
|
||||
|
||||
void _check()
|
||||
{
|
||||
if(_base::success())
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = typename _base::value_type;
|
||||
using string_ref = typename _base::string_ref;
|
||||
|
||||
//! Default construction to empty
|
||||
errored_status_code() = default;
|
||||
//! Copy constructor
|
||||
errored_status_code(const errored_status_code &) = default;
|
||||
//! Move constructor
|
||||
errored_status_code(errored_status_code &&) = default; // NOLINT
|
||||
//! Copy assignment
|
||||
errored_status_code &operator=(const errored_status_code &) = default;
|
||||
//! Move assignment
|
||||
errored_status_code &operator=(errored_status_code &&) = default; // NOLINT
|
||||
~errored_status_code() = default;
|
||||
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(const _base &o) noexcept(std::is_nothrow_copy_constructible<_base>::value)
|
||||
: _base(o)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(_base &&o) noexcept(std::is_nothrow_move_constructible<_base>::value)
|
||||
: _base(static_cast<_base &&>(o))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH STATUS_CODE *****/
|
||||
//! Implicit copy construction from any other status code if its value type is trivially copyable and it would fit into our storage
|
||||
template <class DomainType, //
|
||||
typename std::enable_if<!detail::is_erased_status_code<status_code<DomainType>>::value //
|
||||
&& std::is_trivially_copyable<typename DomainType::value_type>::value //
|
||||
&& detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
|
||||
bool>::type = true>
|
||||
errored_status_code(const status_code<DomainType> &v) noexcept : _base(v) // NOLINT
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Implicit move construction from any other status code if its value type is trivially copyable or move relocating and it would fit into our storage
|
||||
template <class DomainType, //
|
||||
typename std::enable_if<detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
|
||||
bool>::type = true>
|
||||
errored_status_code(status_code<DomainType> &&v) noexcept : _base(static_cast<status_code<DomainType> &&>(v)) // NOLINT
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
template <class T, class... Args, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<!std::is_same<typename std::decay<T>::type, errored_status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, value_type>::value // not copy/move of value type
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<errored_status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
|
||||
bool>::type = true>
|
||||
errored_status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: errored_status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Return the erased `value_type` by value.
|
||||
constexpr value_type value() const noexcept { return this->_value; }
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class ErasedType> struct is_move_relocating<errored_status_code<erased<ErasedType>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator==(const errored_status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator==(const status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator==(const errored_status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return static_cast<const status_code<DomainType1> &>(a).equivalent(b);
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator!=(const errored_status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator!=(const status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator!=(const errored_status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !static_cast<const status_code<DomainType1> &>(a).equivalent(b);
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class DomainType1, class T, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator==(const errored_status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class T, class DomainType1, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator==(const T &a, const errored_status_code<DomainType1> &b)
|
||||
{
|
||||
return b.equivalent(make_status_code(a));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class DomainType1, class T, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator!=(const errored_status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return !a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class T, class DomainType1, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator!=(const T &a, const errored_status_code<DomainType1> &b)
|
||||
{
|
||||
return !b.equivalent(make_status_code(a));
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T> struct is_errored_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_errored_status_code<errored_status_code<T>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <class T> struct is_erased_errored_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_erased_errored_status_code<errored_status_code<erased<T>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
//! Trait returning true if the type is an errored status code.
|
||||
template <class T> struct is_errored_status_code
|
||||
{
|
||||
static constexpr bool value = detail::is_errored_status_code<typename std::decay<T>::type>::value || detail::is_erased_errored_status_code<typename std::decay<T>::type>::value;
|
||||
};
|
||||
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,378 +0,0 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_GENERIC_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP
|
||||
|
||||
#include "status_error.hpp"
|
||||
|
||||
#include <cerrno> // for error constants
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
//! The generic error coding (POSIX)
|
||||
enum class errc : int
|
||||
{
|
||||
success = 0,
|
||||
unknown = -1,
|
||||
|
||||
address_family_not_supported = EAFNOSUPPORT,
|
||||
address_in_use = EADDRINUSE,
|
||||
address_not_available = EADDRNOTAVAIL,
|
||||
already_connected = EISCONN,
|
||||
argument_list_too_long = E2BIG,
|
||||
argument_out_of_domain = EDOM,
|
||||
bad_address = EFAULT,
|
||||
bad_file_descriptor = EBADF,
|
||||
bad_message = EBADMSG,
|
||||
broken_pipe = EPIPE,
|
||||
connection_aborted = ECONNABORTED,
|
||||
connection_already_in_progress = EALREADY,
|
||||
connection_refused = ECONNREFUSED,
|
||||
connection_reset = ECONNRESET,
|
||||
cross_device_link = EXDEV,
|
||||
destination_address_required = EDESTADDRREQ,
|
||||
device_or_resource_busy = EBUSY,
|
||||
directory_not_empty = ENOTEMPTY,
|
||||
executable_format_error = ENOEXEC,
|
||||
file_exists = EEXIST,
|
||||
file_too_large = EFBIG,
|
||||
filename_too_long = ENAMETOOLONG,
|
||||
function_not_supported = ENOSYS,
|
||||
host_unreachable = EHOSTUNREACH,
|
||||
identifier_removed = EIDRM,
|
||||
illegal_byte_sequence = EILSEQ,
|
||||
inappropriate_io_control_operation = ENOTTY,
|
||||
interrupted = EINTR,
|
||||
invalid_argument = EINVAL,
|
||||
invalid_seek = ESPIPE,
|
||||
io_error = EIO,
|
||||
is_a_directory = EISDIR,
|
||||
message_size = EMSGSIZE,
|
||||
network_down = ENETDOWN,
|
||||
network_reset = ENETRESET,
|
||||
network_unreachable = ENETUNREACH,
|
||||
no_buffer_space = ENOBUFS,
|
||||
no_child_process = ECHILD,
|
||||
no_link = ENOLINK,
|
||||
no_lock_available = ENOLCK,
|
||||
no_message = ENOMSG,
|
||||
no_protocol_option = ENOPROTOOPT,
|
||||
no_space_on_device = ENOSPC,
|
||||
no_stream_resources = ENOSR,
|
||||
no_such_device_or_address = ENXIO,
|
||||
no_such_device = ENODEV,
|
||||
no_such_file_or_directory = ENOENT,
|
||||
no_such_process = ESRCH,
|
||||
not_a_directory = ENOTDIR,
|
||||
not_a_socket = ENOTSOCK,
|
||||
not_a_stream = ENOSTR,
|
||||
not_connected = ENOTCONN,
|
||||
not_enough_memory = ENOMEM,
|
||||
not_supported = ENOTSUP,
|
||||
operation_canceled = ECANCELED,
|
||||
operation_in_progress = EINPROGRESS,
|
||||
operation_not_permitted = EPERM,
|
||||
operation_not_supported = EOPNOTSUPP,
|
||||
operation_would_block = EWOULDBLOCK,
|
||||
owner_dead = EOWNERDEAD,
|
||||
permission_denied = EACCES,
|
||||
protcol_error = EPROTO,
|
||||
protocol_not_supported = EPROTONOSUPPORT,
|
||||
read_only_file_system = EROFS,
|
||||
resource_deadlock_would_occur = EDEADLK,
|
||||
resource_unavailable_try_again = EAGAIN,
|
||||
result_out_of_range = ERANGE,
|
||||
state_not_recoverable = ENOTRECOVERABLE,
|
||||
stream_timeout = ETIME,
|
||||
text_file_busy = ETXTBSY,
|
||||
timed_out = ETIMEDOUT,
|
||||
too_many_files_open_in_system = ENFILE,
|
||||
too_many_files_open = EMFILE,
|
||||
too_many_links = EMLINK,
|
||||
too_many_symbolic_link_levels = ELOOP,
|
||||
value_too_large = EOVERFLOW,
|
||||
wrong_protocol_type = EPROTOTYPE
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct generic_code_messages
|
||||
{
|
||||
// libc++ defines missing errc macros to integers in the 9xxx range
|
||||
// As much as 10,000 seems wasteful, bear in mind this is all constexpr
|
||||
// and on C++ 14 or later this entire construct disappears.
|
||||
const char *msgs[(ETIME >= 256) ? 10000 : 256];
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 size_t size() const { return sizeof(msgs) / sizeof(*msgs); } // NOLINT
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 const char *operator[](int i) const { return (i < 0 || i >= static_cast<int>(size()) || nullptr == msgs[i]) ? "unknown" : msgs[i]; } // NOLINT
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 generic_code_messages()
|
||||
: msgs{}
|
||||
{
|
||||
msgs[0] = "Success";
|
||||
|
||||
msgs[EAFNOSUPPORT] = "Address family not supported by protocol";
|
||||
msgs[EADDRINUSE] = "Address already in use";
|
||||
msgs[EADDRNOTAVAIL] = "Cannot assign requested address";
|
||||
msgs[EISCONN] = "Transport endpoint is already connected";
|
||||
msgs[E2BIG] = "Argument list too long";
|
||||
msgs[EDOM] = "Numerical argument out of domain";
|
||||
msgs[EFAULT] = "Bad address";
|
||||
msgs[EBADF] = "Bad file descriptor";
|
||||
msgs[EBADMSG] = "Bad message";
|
||||
msgs[EPIPE] = "Broken pipe";
|
||||
msgs[ECONNABORTED] = "Software caused connection abort";
|
||||
msgs[EALREADY] = "Operation already in progress";
|
||||
msgs[ECONNREFUSED] = "Connection refused";
|
||||
msgs[ECONNRESET] = "Connection reset by peer";
|
||||
msgs[EXDEV] = "Invalid cross-device link";
|
||||
msgs[EDESTADDRREQ] = "Destination address required";
|
||||
msgs[EBUSY] = "Device or resource busy";
|
||||
msgs[ENOTEMPTY] = "Directory not empty";
|
||||
msgs[ENOEXEC] = "Exec format error";
|
||||
msgs[EEXIST] = "File exists";
|
||||
msgs[EFBIG] = "File too large";
|
||||
msgs[ENAMETOOLONG] = "File name too long";
|
||||
msgs[ENOSYS] = "Function not implemented";
|
||||
msgs[EHOSTUNREACH] = "No route to host";
|
||||
msgs[EIDRM] = "Identifier removed";
|
||||
msgs[EILSEQ] = "Invalid or incomplete multibyte or wide character";
|
||||
msgs[ENOTTY] = "Inappropriate ioctl for device";
|
||||
msgs[EINTR] = "Interrupted system call";
|
||||
msgs[EINVAL] = "Invalid argument";
|
||||
msgs[ESPIPE] = "Illegal seek";
|
||||
msgs[EIO] = "Input/output error";
|
||||
msgs[EISDIR] = "Is a directory";
|
||||
msgs[EMSGSIZE] = "Message too long";
|
||||
msgs[ENETDOWN] = "Network is down";
|
||||
msgs[ENETRESET] = "Network dropped connection on reset";
|
||||
msgs[ENETUNREACH] = "Network is unreachable";
|
||||
msgs[ENOBUFS] = "No buffer space available";
|
||||
msgs[ECHILD] = "No child processes";
|
||||
msgs[ENOLINK] = "Link has been severed";
|
||||
msgs[ENOLCK] = "No locks available";
|
||||
msgs[ENOMSG] = "No message of desired type";
|
||||
msgs[ENOPROTOOPT] = "Protocol not available";
|
||||
msgs[ENOSPC] = "No space left on device";
|
||||
msgs[ENOSR] = "Out of streams resources";
|
||||
msgs[ENXIO] = "No such device or address";
|
||||
msgs[ENODEV] = "No such device";
|
||||
msgs[ENOENT] = "No such file or directory";
|
||||
msgs[ESRCH] = "No such process";
|
||||
msgs[ENOTDIR] = "Not a directory";
|
||||
msgs[ENOTSOCK] = "Socket operation on non-socket";
|
||||
msgs[ENOSTR] = "Device not a stream";
|
||||
msgs[ENOTCONN] = "Transport endpoint is not connected";
|
||||
msgs[ENOMEM] = "Cannot allocate memory";
|
||||
msgs[ENOTSUP] = "Operation not supported";
|
||||
msgs[ECANCELED] = "Operation canceled";
|
||||
msgs[EINPROGRESS] = "Operation now in progress";
|
||||
msgs[EPERM] = "Operation not permitted";
|
||||
msgs[EOPNOTSUPP] = "Operation not supported";
|
||||
msgs[EWOULDBLOCK] = "Resource temporarily unavailable";
|
||||
msgs[EOWNERDEAD] = "Owner died";
|
||||
msgs[EACCES] = "Permission denied";
|
||||
msgs[EPROTO] = "Protocol error";
|
||||
msgs[EPROTONOSUPPORT] = "Protocol not supported";
|
||||
msgs[EROFS] = "Read-only file system";
|
||||
msgs[EDEADLK] = "Resource deadlock avoided";
|
||||
msgs[EAGAIN] = "Resource temporarily unavailable";
|
||||
msgs[ERANGE] = "Numerical result out of range";
|
||||
msgs[ENOTRECOVERABLE] = "State not recoverable";
|
||||
msgs[ETIME] = "Timer expired";
|
||||
msgs[ETXTBSY] = "Text file busy";
|
||||
msgs[ETIMEDOUT] = "Connection timed out";
|
||||
msgs[ENFILE] = "Too many open files in system";
|
||||
msgs[EMFILE] = "Too many open files";
|
||||
msgs[EMLINK] = "Too many links";
|
||||
msgs[ELOOP] = "Too many levels of symbolic links";
|
||||
msgs[EOVERFLOW] = "Value too large for defined data type";
|
||||
msgs[EPROTOTYPE] = "Protocol wrong type for socket";
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/*! The implementation of the domain for generic status codes, those mapped by `errc` (POSIX).
|
||||
*/
|
||||
class _generic_code_domain : public status_code_domain
|
||||
{
|
||||
template <class> friend class status_code;
|
||||
template <class StatusCode> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
|
||||
public:
|
||||
//! The value type of the generic code, which is an `errc` as per POSIX.
|
||||
using value_type = errc;
|
||||
using string_ref = _base::string_ref;
|
||||
|
||||
public:
|
||||
//! Default constructor
|
||||
constexpr explicit _generic_code_domain(typename _base::unique_id_type id = 0x746d6354f4f733e9) noexcept : _base(id) {}
|
||||
_generic_code_domain(const _generic_code_domain &) = default;
|
||||
_generic_code_domain(_generic_code_domain &&) = default;
|
||||
_generic_code_domain &operator=(const _generic_code_domain &) = default;
|
||||
_generic_code_domain &operator=(_generic_code_domain &&) = default;
|
||||
~_generic_code_domain() = default;
|
||||
|
||||
//! Constexpr singleton getter. Returns the constexpr generic_code_domain variable.
|
||||
static inline constexpr const _generic_code_domain &get();
|
||||
|
||||
virtual _base::string_ref name() const noexcept override { return string_ref("generic domain"); } // NOLINT
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const generic_code &>(code).value() != errc::success; // NOLINT
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this); // NOLINT
|
||||
const auto &c1 = static_cast<const generic_code &>(code1); // NOLINT
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
|
||||
return c1.value() == c2.value();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const generic_code &>(code); // NOLINT
|
||||
}
|
||||
virtual _base::string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const generic_code &>(code); // NOLINT
|
||||
static BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 detail::generic_code_messages msgs;
|
||||
return string_ref(msgs[static_cast<int>(c.value())]);
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const generic_code &>(code); // NOLINT
|
||||
throw status_error<_generic_code_domain>(c);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
//! A specialisation of `status_error` for the generic code domain.
|
||||
using generic_error = status_error<_generic_code_domain>;
|
||||
//! A constexpr source variable for the generic code domain, which is that of `errc` (POSIX). Returned by `_generic_code_domain::get()`.
|
||||
constexpr _generic_code_domain generic_code_domain;
|
||||
inline constexpr const _generic_code_domain &_generic_code_domain::get()
|
||||
{
|
||||
return generic_code_domain;
|
||||
}
|
||||
// Enable implicit construction of generic_code from errc
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline generic_code make_status_code(errc c) noexcept
|
||||
{
|
||||
return generic_code(in_place, c);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
|
||||
template <class T> inline bool status_code<void>::equivalent(const status_code<T> &o) const noexcept
|
||||
{
|
||||
if(_domain && o._domain)
|
||||
{
|
||||
if(_domain->_do_equivalent(*this, o))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(o._domain->_do_equivalent(o, *this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
generic_code c1 = o._domain->_generic_code(o);
|
||||
if(c1.value() != errc::unknown && _domain->_do_equivalent(*this, c1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
generic_code c2 = _domain->_generic_code(*this);
|
||||
if(c2.value() != errc::unknown && o._domain->_do_equivalent(o, c2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If we are both empty, we are equivalent, otherwise not equivalent
|
||||
return (!_domain && !o._domain);
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator==(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return a.equivalent(b);
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator!=(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !a.equivalent(b);
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class DomainType1, class T, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator==(const status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class T, class DomainType1, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator==(const T &a, const status_code<DomainType1> &b)
|
||||
{
|
||||
return b.equivalent(make_status_code(a));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class DomainType1, class T, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator!=(const status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return !a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
template <class T, class DomainType1, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
|
||||
inline bool
|
||||
operator!=(const T &a, const status_code<DomainType1> &b)
|
||||
{
|
||||
return !b.equivalent(make_status_code(a));
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,335 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018 - 2022 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Mar 2022
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_BOOST_ERROR_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_BOOST_ERROR_CODE_HPP
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
|
||||
#include "posix_code.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
#include "win32_code.hpp"
|
||||
#endif
|
||||
|
||||
#include "std_error_code.hpp"
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
#include <system_error>
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
class _boost_error_code_domain;
|
||||
//! A `status_code` representing exactly a `boost::system::error_code`
|
||||
using boost_error_code = status_code<_boost_error_code_domain>;
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> struct mixin<Base, _boost_error_code_domain> : public Base
|
||||
{
|
||||
using Base::Base;
|
||||
|
||||
//! Implicit constructor from a `boost::system::error_code`
|
||||
inline mixin(boost::system::error_code ec);
|
||||
|
||||
//! Returns the error code category
|
||||
inline const boost::system::error_category &category() const noexcept;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
|
||||
/*! The implementation of the domain for `boost::system::error_code` error codes.
|
||||
*/
|
||||
class _boost_error_code_domain final : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
using _error_code_type = boost::system::error_code;
|
||||
using _error_category_type = boost::system::error_category;
|
||||
|
||||
std::string _name;
|
||||
|
||||
static _base::string_ref _make_string_ref(_error_code_type c) noexcept
|
||||
{
|
||||
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
||||
try
|
||||
#endif
|
||||
{
|
||||
std::string msg = c.message();
|
||||
auto *p = static_cast<char *>(malloc(msg.size() + 1)); // NOLINT
|
||||
if(p == nullptr)
|
||||
{
|
||||
return _base::string_ref("failed to allocate message");
|
||||
}
|
||||
memcpy(p, msg.c_str(), msg.size() + 1);
|
||||
return _base::atomic_refcounted_string_ref(p, msg.size());
|
||||
}
|
||||
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
||||
catch(...)
|
||||
{
|
||||
return _base::string_ref("failed to allocate message");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
//! The value type of the `boost::system::error_code` code, which stores the `int` from the `boost::system::error_code`
|
||||
using value_type = int;
|
||||
using _base::string_ref;
|
||||
|
||||
//! Returns the error category singleton pointer this status code domain represents
|
||||
const _error_category_type &error_category() const noexcept
|
||||
{
|
||||
auto ptr = 0x0ea88ff382d94915 ^ this->id();
|
||||
return *reinterpret_cast<const _error_category_type *>(ptr);
|
||||
}
|
||||
|
||||
//! Default constructor
|
||||
explicit _boost_error_code_domain(const _error_category_type &category) noexcept
|
||||
: _base(0x0ea88ff382d94915 ^ reinterpret_cast<_base::unique_id_type>(&category))
|
||||
, _name("boost_error_code_domain(")
|
||||
{
|
||||
_name.append(category.name());
|
||||
_name.push_back(')');
|
||||
}
|
||||
_boost_error_code_domain(const _boost_error_code_domain &) = default;
|
||||
_boost_error_code_domain(_boost_error_code_domain &&) = default;
|
||||
_boost_error_code_domain &operator=(const _boost_error_code_domain &) = default;
|
||||
_boost_error_code_domain &operator=(_boost_error_code_domain &&) = default;
|
||||
~_boost_error_code_domain() = default;
|
||||
|
||||
static inline const _boost_error_code_domain *get(_error_code_type ec);
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref(_name.c_str(), _name.size()); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override;
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override;
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override;
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override;
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override;
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
extern inline _boost_error_code_domain *boost_error_code_domain_from_category(const boost::system::error_category &category)
|
||||
{
|
||||
static constexpr size_t max_items = 64;
|
||||
static struct storage_t
|
||||
{
|
||||
std::atomic<unsigned> _lock;
|
||||
union item_t
|
||||
{
|
||||
int _init;
|
||||
_boost_error_code_domain domain;
|
||||
constexpr item_t()
|
||||
: _init(0)
|
||||
{
|
||||
}
|
||||
~item_t() {}
|
||||
} items[max_items];
|
||||
size_t count{0};
|
||||
|
||||
void lock()
|
||||
{
|
||||
while(_lock.exchange(1, std::memory_order_acquire) != 0)
|
||||
;
|
||||
}
|
||||
void unlock() { _lock.store(0, std::memory_order_release); }
|
||||
|
||||
storage_t() {}
|
||||
~storage_t()
|
||||
{
|
||||
lock();
|
||||
for(size_t n = 0; n < count; n++)
|
||||
{
|
||||
items[n].domain.~_boost_error_code_domain();
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
_boost_error_code_domain *add(const boost::system::error_category &category)
|
||||
{
|
||||
_boost_error_code_domain *ret = nullptr;
|
||||
lock();
|
||||
for(size_t n = 0; n < count; n++)
|
||||
{
|
||||
if(items[n].domain.error_category() == category)
|
||||
{
|
||||
ret = &items[n].domain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ret == nullptr && count < max_items)
|
||||
{
|
||||
ret = new(BOOST_OUTCOME_SYSTEM_ERROR2_ADDRESS_OF(items[count++].domain)) _boost_error_code_domain(category);
|
||||
}
|
||||
unlock();
|
||||
return ret;
|
||||
}
|
||||
} storage;
|
||||
return storage.add(category);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base>
|
||||
inline mixin<Base, _boost_error_code_domain>::mixin(boost::system::error_code ec)
|
||||
: Base(typename Base::_value_type_constructor{}, _boost_error_code_domain::get(ec), ec.value())
|
||||
{
|
||||
}
|
||||
|
||||
template <class Base> inline const boost::system::error_category &mixin<Base, _boost_error_code_domain>::category() const noexcept
|
||||
{
|
||||
const auto &domain = static_cast<const _boost_error_code_domain &>(this->domain());
|
||||
return domain.error_category();
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
inline const _boost_error_code_domain *_boost_error_code_domain::get(boost::system::error_code ec)
|
||||
{
|
||||
auto *p = detail::boost_error_code_domain_from_category(ec.category());
|
||||
assert(p != nullptr);
|
||||
if(p == nullptr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
inline bool _boost_error_code_domain::_do_failure(const status_code<void> &code) const noexcept
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
return static_cast<const boost_error_code &>(code).value() != 0; // NOLINT
|
||||
}
|
||||
|
||||
inline bool _boost_error_code_domain::_do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept
|
||||
{
|
||||
assert(code1.domain() == *this);
|
||||
const auto &c1 = static_cast<const boost_error_code &>(code1); // NOLINT
|
||||
const auto &cat1 = c1.category();
|
||||
// Are we comparing to another wrapped error_code?
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const boost_error_code &>(code2); // NOLINT
|
||||
const auto &cat2 = c2.category();
|
||||
// If the error code categories are identical, do literal comparison
|
||||
if(cat1 == cat2)
|
||||
{
|
||||
return c1.value() == c2.value();
|
||||
}
|
||||
// Otherwise fall back onto the _generic_code comparison, which uses default_error_condition()
|
||||
return false;
|
||||
}
|
||||
// Am I an error code with generic category?
|
||||
if(cat1 == boost::system::generic_category())
|
||||
{
|
||||
// Convert to generic code, and compare that
|
||||
generic_code _c1(static_cast<errc>(c1.value()));
|
||||
return _c1 == code2;
|
||||
}
|
||||
// Am I an error code with system category?
|
||||
if(cat1 == boost::system::system_category())
|
||||
{
|
||||
// Convert to POSIX or Win32 code, and compare that
|
||||
#ifdef _WIN32
|
||||
win32_code _c1((win32::DWORD) c1.value());
|
||||
return _c1 == code2;
|
||||
#elif !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX)
|
||||
posix_code _c1(c1.value());
|
||||
return _c1 == code2;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline generic_code _boost_error_code_domain::_generic_code(const status_code<void> &code) const noexcept
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const boost_error_code &>(code); // NOLINT
|
||||
// Ask my embedded error code for its mapping to boost::system::errc, which is a subset of our generic_code errc.
|
||||
boost::system::error_condition cond(c.category().default_error_condition(c.value()));
|
||||
if(cond.category() == boost::system::generic_category())
|
||||
{
|
||||
return generic_code(static_cast<errc>(cond.value()));
|
||||
}
|
||||
#if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX) && !defined(_WIN32)
|
||||
if(cond.category() == boost::system::system_category())
|
||||
{
|
||||
return generic_code(static_cast<errc>(cond.value()));
|
||||
}
|
||||
#endif
|
||||
return errc::unknown;
|
||||
}
|
||||
|
||||
inline _boost_error_code_domain::string_ref _boost_error_code_domain::_do_message(const status_code<void> &code) const noexcept
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const boost_error_code &>(code); // NOLINT
|
||||
return _make_string_ref(_error_code_type(c.value(), c.category()));
|
||||
}
|
||||
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN inline void _boost_error_code_domain::_do_throw_exception(const status_code<void> &code) const
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const boost_error_code &>(code); // NOLINT
|
||||
throw boost::system::system_error(boost::system::error_code(c.value(), c.category()));
|
||||
}
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(boost_error_code) <= sizeof(void *) * 2, "boost_error_code does not fit into a system_code!");
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
// Enable implicit construction of `boost_error_code` from `boost::system::error_code`.
|
||||
namespace boost
|
||||
{
|
||||
namespace system
|
||||
{
|
||||
inline BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::erased_status_code<int> make_status_code(error_code c) noexcept
|
||||
{
|
||||
if(c.category() == detail::interop_category())
|
||||
{
|
||||
// This is actually a wrap of std::error_code. If this fails to compile, your Boost is too old.
|
||||
return std::make_status_code(std::error_code(c));
|
||||
}
|
||||
return BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::boost_error_code(c);
|
||||
}
|
||||
} // namespace system
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -46,10 +46,10 @@ BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
class _com_code_domain;
|
||||
/*! (Windows only) A COM error code. Note semantic equivalence testing is only implemented for `FACILITY_WIN32`
|
||||
and `FACILITY_NT_BIT`. As you can see at [https://blogs.msdn.microsoft.com/eldar/2007/04/03/a-lot-of-hresult-codes/](https://blogs.msdn.microsoft.com/eldar/2007/04/03/a-lot-of-hresult-codes/),
|
||||
there are an awful lot of COM error codes, and keeping mapping tables for all of them would be impractical
|
||||
(for the Win32 and NT facilities, we actually reuse the mapping tables in `win32_code` and `nt_code`).
|
||||
You can, of course, inherit your own COM code domain from this one and override the `_do_equivalent()` function
|
||||
and `FACILITY_NT_BIT`. As you can see at
|
||||
[https://blogs.msdn.microsoft.com/eldar/2007/04/03/a-lot-of-hresult-codes/](https://blogs.msdn.microsoft.com/eldar/2007/04/03/a-lot-of-hresult-codes/), there
|
||||
are an awful lot of COM error codes, and keeping mapping tables for all of them would be impractical (for the Win32 and NT facilities, we actually reuse the
|
||||
mapping tables in `win32_code` and `nt_code`). You can, of course, inherit your own COM code domain from this one and override the `_do_equivalent()` function
|
||||
to add semantic equivalence testing for whichever extra COM codes that your application specifically needs.
|
||||
*/
|
||||
using com_code = status_code<_com_code_domain>;
|
||||
@@ -57,15 +57,19 @@ using com_code = status_code<_com_code_domain>;
|
||||
using com_error = status_error<_com_code_domain>;
|
||||
|
||||
/*! (Windows only) The implementation of the domain for COM error codes and/or `IErrorInfo`.
|
||||
*/
|
||||
*/
|
||||
class _com_code_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode> friend class detail::indirecting_domain;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
|
||||
//! Construct from a `HRESULT` error code
|
||||
#ifdef _COMDEF_NOT_WINAPI_FAMILY_DESKTOP_APP
|
||||
static _base::string_ref _make_string_ref(HRESULT c, wchar_t *perrinfo = nullptr) noexcept
|
||||
#else
|
||||
static _base::string_ref _make_string_ref(HRESULT c, IErrorInfo *perrinfo = nullptr) noexcept
|
||||
#endif
|
||||
{
|
||||
_com_error ce(c, perrinfo);
|
||||
#ifdef _UNICODE
|
||||
@@ -83,7 +87,7 @@ class _com_code_domain : public status_code_domain
|
||||
{
|
||||
return _base::string_ref("failed to get message from system");
|
||||
}
|
||||
bytes = win32::WideCharToMultiByte(65001 /*CP_UTF8*/, 0, ce.ErrorMessage(), wlen + 1, p, allocation, nullptr, nullptr);
|
||||
bytes = win32::WideCharToMultiByte(65001 /*CP_UTF8*/, 0, ce.ErrorMessage(), (int) (wlen + 1), p, (int) allocation, nullptr, nullptr);
|
||||
if(bytes != 0)
|
||||
{
|
||||
char *end = strchr(p, 0);
|
||||
@@ -127,7 +131,10 @@ public:
|
||||
|
||||
public:
|
||||
//! Default constructor
|
||||
constexpr explicit _com_code_domain(typename _base::unique_id_type id = 0xdc8275428b4effac) noexcept : _base(id) {}
|
||||
constexpr explicit _com_code_domain(typename _base::unique_id_type id = 0xdc8275428b4effac) noexcept
|
||||
: _base(id)
|
||||
{
|
||||
}
|
||||
_com_code_domain(const _com_code_domain &) = default;
|
||||
_com_code_domain(_com_code_domain &&) = default;
|
||||
_com_code_domain &operator=(const _com_code_domain &) = default;
|
||||
@@ -138,6 +145,13 @@ public:
|
||||
static inline constexpr const _com_code_domain &get();
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref("COM domain"); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
@@ -145,7 +159,7 @@ protected:
|
||||
return static_cast<const com_code &>(code).value() < 0; // NOLINT
|
||||
}
|
||||
/*! Note semantic equivalence testing is only implemented for `FACILITY_WIN32` and `FACILITY_NT_BIT`.
|
||||
*/
|
||||
*/
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this);
|
||||
@@ -0,0 +1,459 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018 - 2021 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_CONFIG_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONFIG_HPP
|
||||
|
||||
// < 0.1 each
|
||||
#include <cassert>
|
||||
#include <cstddef> // for size_t
|
||||
#include <cstdlib> // for free
|
||||
|
||||
// 0.22
|
||||
#include <type_traits>
|
||||
|
||||
// 0.29
|
||||
#include <atomic>
|
||||
|
||||
// 0.28 (0.15 of which is exception_ptr)
|
||||
#include <exception> // for std::exception
|
||||
// <new> includes <exception>, <exception> includes <new>
|
||||
#include <new>
|
||||
|
||||
// 0.01
|
||||
#include <initializer_list>
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
|
||||
#ifdef __has_include
|
||||
#if __has_include(<bit>) && (__cplusplus >= 202002L || _HAS_CXX20)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 1
|
||||
#endif
|
||||
#elif __cplusplus >= 202002L
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 1
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 0
|
||||
#endif
|
||||
#endif
|
||||
#if BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
|
||||
#include <bit>
|
||||
#if __cpp_lib_bit_cast < 201806L
|
||||
#undef BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BOOST_OUTCOME_SYSTEM_ERROR2_USE_STD_ADDRESSOF
|
||||
#include <memory> // for std::addressof
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_ADDRESS_OF(...) std::addressof(__VA_ARGS__)
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_ADDRESS_OF(...) (&__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
|
||||
//! Defined to be `constexpr` when on C++ 14 or better compilers. Usually automatic, can be overriden.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 constexpr
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || __cplusplus >= 202000 || _HAS_CXX20
|
||||
//! Defined to be `constexpr` when on C++ 20 or better compilers. Usually automatic, can be overriden.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 constexpr
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN [[noreturn]]
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN)
|
||||
#ifdef __has_cpp_attribute
|
||||
#if __has_cpp_attribute(noreturn)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN [[noreturn]]
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN)
|
||||
#if defined(_MSC_VER)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN __declspec(noreturn)
|
||||
#elif defined(__GNUC__)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN __attribute__((__noreturn__))
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#endif
|
||||
#endif
|
||||
// GCCs before 7 don't grok [[noreturn]] virtual functions, and warn annoyingly
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 7
|
||||
#undef BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD [[nodiscard]]
|
||||
#endif
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#ifdef __has_cpp_attribute
|
||||
#if __has_cpp_attribute(nodiscard)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD [[nodiscard]]
|
||||
#endif
|
||||
#elif defined(__clang__)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD __attribute__((warn_unused_result))
|
||||
#elif defined(_MSC_VER)
|
||||
// _Must_inspect_result_ expands into this
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD \
|
||||
__declspec( \
|
||||
"SAL_name" \
|
||||
"(" \
|
||||
"\"_Must_inspect_result_\"" \
|
||||
"," \
|
||||
"\"\"" \
|
||||
"," \
|
||||
"\"2\"" \
|
||||
")") __declspec("SAL_begin") __declspec("SAL_post") __declspec("SAL_mustInspect") __declspec("SAL_post") __declspec("SAL_checkReturn") __declspec("SAL_end")
|
||||
#endif
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI
|
||||
#if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (__clang_major__ >= 7 && !defined(__APPLE__))
|
||||
//! Defined to be `[[clang::trivial_abi]]` when on a new enough clang compiler. Usually automatic, can be overriden.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI [[clang::trivial_abi]]
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_concepts) && !defined(BOOST_OUTCOME_SYSTEM_ERROR2_DISABLE_CONCEPTS_SUPPORT)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_GLUE(x, y) x y
|
||||
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_EXPAND_ARGS(args) BOOST_OUTCOME_SYSTEM_ERROR2_RETURN_ARG_COUNT args
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_COUNT_ARGS_MAX8(...) BOOST_OUTCOME_SYSTEM_ERROR2_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO2(name, count) name##count
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO1(name, count) BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO2(name, count)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO(name, count) BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO1(name, count)
|
||||
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_CALL_OVERLOAD(name, ...) BOOST_OUTCOME_SYSTEM_ERROR2_GLUE(BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO(name, BOOST_OUTCOME_SYSTEM_ERROR2_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
|
||||
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND8(a, b, c, d, e, f, g, h) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND7(b, c, d, e, f, g, h)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND7(a, b, c, d, e, f, g) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND6(b, c, d, e, f, g)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND6(a, b, c, d, e, f) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND5(b, c, d, e, f)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND5(a, b, c, d, e) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND4(b, c, d, e)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND4(a, b, c, d) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND3(b, c, d)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND3(a, b, c) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND2(b, c)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND2(a, b) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND1(b)
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND1(a) a
|
||||
|
||||
//! Expands into a && b && c && ...
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(...) requires BOOST_OUTCOME_SYSTEM_ERROR2_CALL_OVERLOAD(BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND, __VA_ARGS__)
|
||||
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(...) template <__VA_ARGS__>
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TEXPR(...) \
|
||||
requires { (__VA_ARGS__); }
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(...) (__VA_ARGS__)
|
||||
#if !defined(_MSC_VER) || _MSC_FULL_VER >= 192400000 // VS 2019 16.3 is broken here
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_REQUIRES(...) requires(__VA_ARGS__)
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_REQUIRES(...)
|
||||
#endif
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(...) template <__VA_ARGS__
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(...) , __VA_ARGS__ >
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TEXPR(...) typename = decltype(__VA_ARGS__)
|
||||
#ifdef _MSC_VER
|
||||
// MSVC gives an error if every specialisation of a template is always ill-formed, so
|
||||
// the more powerful SFINAE form below causes pukeage :(
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(...) typename = typename std::enable_if<(__VA_ARGS__)>::type
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(...) typename std::enable_if<(__VA_ARGS__), bool>::type = true
|
||||
#endif
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_REQUIRES(...)
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE
|
||||
//! The system_error2 namespace name.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE system_error2
|
||||
//! Begins the system_error2 namespace.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN \
|
||||
namespace system_error2 \
|
||||
{
|
||||
//! Ends the system_error2 namespace.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END }
|
||||
#endif
|
||||
|
||||
//! Namespace for the library
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
//! Namespace for user specialised traits
|
||||
namespace traits
|
||||
{
|
||||
/*! Specialise to true if you guarantee that a type is move bitcopying (i.e.
|
||||
its move constructor equals copying bits from old to new, old is left in a
|
||||
default constructed state, and calling the destructor on a default constructed
|
||||
instance is trivial). All trivially copyable types are move bitcopying by
|
||||
definition, and that is the unspecialised implementation.
|
||||
*/
|
||||
template <class T> struct is_move_bitcopying
|
||||
{
|
||||
static constexpr bool value = std::is_trivially_copyable<T>::value;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
|
||||
inline constexpr size_t cstrlen(const char *str)
|
||||
{
|
||||
const char *end = nullptr;
|
||||
for(end = str; *end != 0; ++end) // NOLINT
|
||||
;
|
||||
return end - str;
|
||||
}
|
||||
#else
|
||||
inline constexpr size_t cstrlen_(const char *str, size_t acc) { return (str[0] == 0) ? acc : cstrlen_(str + 1, acc + 1); }
|
||||
inline constexpr size_t cstrlen(const char *str) { return cstrlen_(str, 0); }
|
||||
#endif
|
||||
|
||||
#if(__cplusplus >= 202002L || _MSVC_LANG >= 202002L) && __cpp_lib_remove_cvref >= 201711L
|
||||
|
||||
template <class T> using remove_cvref = std::remove_cvref<T>;
|
||||
|
||||
#else
|
||||
|
||||
template <class T> struct remove_cvref
|
||||
{
|
||||
using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* A partially compliant implementation of C++20's std::bit_cast function contributed
|
||||
by Jesse Towner.
|
||||
|
||||
Our bit_cast is only guaranteed to be constexpr when both the input and output
|
||||
arguments are either integrals or enums. However, this covers most use cases
|
||||
since the vast majority of status_codes have an underlying type that is either
|
||||
an integral or enum. We still attempt a constexpr union-based type pun for non-array
|
||||
input types, which some compilers accept. For array inputs, we fall back to
|
||||
non-constexpr memmove.
|
||||
*/
|
||||
|
||||
template <class T> using is_integral_or_enum = std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value>;
|
||||
|
||||
template <class To, class From> using is_static_castable = std::integral_constant<bool, is_integral_or_enum<To>::value && is_integral_or_enum<From>::value>;
|
||||
|
||||
template <class To, class From>
|
||||
using is_union_castable = std::integral_constant<bool, !is_static_castable<To, From>::value && !std::is_array<To>::value && !std::is_array<From>::value>;
|
||||
|
||||
template <class To, class From>
|
||||
using is_bit_castable =
|
||||
std::integral_constant<bool, sizeof(To) == sizeof(From) && traits::is_move_bitcopying<To>::value && traits::is_move_bitcopying<From>::value>;
|
||||
|
||||
template <class To, class From> union bit_cast_union
|
||||
{
|
||||
From source;
|
||||
To target;
|
||||
};
|
||||
|
||||
#if BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
|
||||
using std::bit_cast; // available for all trivially copyable types
|
||||
|
||||
// For move bit copying types
|
||||
template <class To, class From>
|
||||
requires(is_bit_castable<To, From>::value //
|
||||
&&is_union_castable<To, From>::value //
|
||||
&& (!std::is_trivially_copyable_v<From> //
|
||||
|| !std::is_trivially_copyable_v<To>) ) //
|
||||
constexpr To bit_cast(const From &from) noexcept
|
||||
{
|
||||
return bit_cast_union<To, From>{from}.target;
|
||||
}
|
||||
template <class To, class From>
|
||||
requires(is_bit_castable<To, From>::value //
|
||||
&& !is_union_castable<To, From>::value //
|
||||
&& (!std::is_trivially_copyable_v<From> //
|
||||
|| !std::is_trivially_copyable_v<To>) ) //
|
||||
To bit_cast(const From &from)
|
||||
noexcept
|
||||
{
|
||||
bit_cast_union<To, From> ret;
|
||||
memmove(&ret.source, &from, sizeof(ret.source));
|
||||
return ret.target;
|
||||
}
|
||||
#else
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, int = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_bit_castable<To, From>::value //
|
||||
&&is_static_castable<To, From>::value //
|
||||
&& !is_union_castable<To, From>::value))
|
||||
constexpr To bit_cast(const From &from) noexcept { return static_cast<To>(from); }
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, long = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_bit_castable<To, From>::value //
|
||||
&& !is_static_castable<To, From>::value //
|
||||
&& is_union_castable<To, From>::value))
|
||||
constexpr To bit_cast(const From &from) noexcept { return bit_cast_union<To, From>{from}.target; }
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, short = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_bit_castable<To, From>::value //
|
||||
&& !is_static_castable<To, From>::value //
|
||||
&& !is_union_castable<To, From>::value))
|
||||
To bit_cast(const From &from) noexcept
|
||||
{
|
||||
bit_cast_union<To, From> ret;
|
||||
memmove(&ret.source, &from, sizeof(ret.source));
|
||||
return ret.target;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* erasure_cast performs a bit_cast with additional rules to handle types
|
||||
of differing sizes. For integral & enum types, it may perform a narrowing
|
||||
or widing conversion with static_cast if necessary, before doing the final
|
||||
conversion with bit_cast. When casting to or from non-integral, non-enum
|
||||
types it may insert the value into another object with extra padding bytes
|
||||
to satisfy bit_cast's preconditions that both types have the same size. */
|
||||
|
||||
template <class To, class From>
|
||||
using is_erasure_castable = std::integral_constant<bool, traits::is_move_bitcopying<To>::value && traits::is_move_bitcopying<From>::value>;
|
||||
|
||||
template <class T, bool = std::is_enum<T>::value> struct identity_or_underlying_type
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
template <class T> struct identity_or_underlying_type<T, true>
|
||||
{
|
||||
using type = typename std::underlying_type<T>::type;
|
||||
};
|
||||
|
||||
template <class OfSize, class OfSign>
|
||||
using erasure_integer_type = typename std::conditional<std::is_signed<typename identity_or_underlying_type<OfSign>::type>::value,
|
||||
typename std::make_signed<typename identity_or_underlying_type<OfSize>::type>::type,
|
||||
typename std::make_unsigned<typename identity_or_underlying_type<OfSize>::type>::type>::type;
|
||||
|
||||
template <class ErasedType, std::size_t N> struct padded_erasure_object
|
||||
{
|
||||
static_assert(traits::is_move_bitcopying<ErasedType>::value, "ErasedType must be TriviallyCopyable or MoveBitcopying");
|
||||
static_assert(alignof(ErasedType) <= sizeof(ErasedType), "ErasedType must not be over-aligned");
|
||||
ErasedType value;
|
||||
char padding[N];
|
||||
constexpr explicit padded_erasure_object(const ErasedType &v) noexcept
|
||||
: value(v)
|
||||
, padding{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && (sizeof(To) == sizeof(From))))
|
||||
constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(from); }
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__) || __LITTLE_ENDIAN__ || (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
// We can avoid the type pun on little endian architectures which can aid optimisation
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, long = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value &&is_static_castable<To, From>::value && (sizeof(To) < sizeof(From))))
|
||||
constexpr To erasure_cast(const From &from) noexcept { return static_cast<To>(bit_cast<erasure_integer_type<From, To>>(from)); }
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, int = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value &&is_static_castable<To, From>::value && (sizeof(To) > sizeof(From))))
|
||||
constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(static_cast<erasure_integer_type<To, From>>(from)); }
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, short = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) < sizeof(From))))
|
||||
constexpr To erasure_cast(const From &from) noexcept { return bit_cast<padded_erasure_object<To, sizeof(From) - sizeof(To)>>(from).value; }
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, char = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) > sizeof(From))))
|
||||
constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(padded_erasure_object<From, sizeof(To) - sizeof(From)>{from}); }
|
||||
#else
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, short = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && (sizeof(To) < sizeof(From))))
|
||||
constexpr To erasure_cast(const From &from) noexcept { return bit_cast<padded_erasure_object<To, sizeof(From) - sizeof(To)>>(from).value; }
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, char = 5)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && (sizeof(To) > sizeof(From))))
|
||||
constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(padded_erasure_object<From, sizeof(To) - sizeof(From)>{from}); }
|
||||
#endif
|
||||
} // namespace detail
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_FATAL
|
||||
#ifdef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
|
||||
#error If BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX is defined, you must define your own BOOST_OUTCOME_SYSTEM_ERROR2_FATAL implementation!
|
||||
#endif
|
||||
#include <cstdlib> // for abort
|
||||
#ifdef __APPLE__
|
||||
#include <unistd.h> // for write
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
{
|
||||
namespace avoid_stdio_include
|
||||
{
|
||||
#if !defined(__APPLE__) && !defined(_MSC_VER)
|
||||
extern "C" ptrdiff_t write(int, const void *, size_t);
|
||||
#elif defined(_MSC_VER)
|
||||
extern ptrdiff_t write(int, const void *, size_t);
|
||||
#if(defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64)) || (defined(__arm__) || defined(_M_ARM))
|
||||
#pragma comment(linker, "/alternatename:?write@avoid_stdio_include@detail@system_error2@@YA_JHPEBX_K@Z=write")
|
||||
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
|
||||
#pragma comment(linker, "/alternatename:?write@avoid_stdio_include@detail@system_error2@@YAHHPBXI@Z=_write")
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
#endif
|
||||
} // namespace avoid_stdio_include
|
||||
inline void do_fatal_exit(const char *msg)
|
||||
{
|
||||
using namespace avoid_stdio_include;
|
||||
write(2 /*stderr*/, msg, cstrlen(msg));
|
||||
write(2 /*stderr*/, "\n", 1);
|
||||
abort();
|
||||
}
|
||||
} // namespace detail
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
//! Prints msg to stderr, and calls `std::terminate()`. Can be overriden via predefinition.
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_FATAL(msg) ::BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::detail::do_fatal_exit(msg)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
/*! An erased `system_code` which is always a failure. The closest equivalent to
|
||||
/*! An errored `system_code` which is always a failure. The closest equivalent to
|
||||
`std::error_code`, except it cannot be null and cannot be modified.
|
||||
|
||||
This refines `system_code` into an `error` object meeting the requirements of
|
||||
@@ -51,13 +51,13 @@ the program is terminated as this is a logic error)
|
||||
- Is immutable.
|
||||
|
||||
As with `system_code`, it remains guaranteed to be two CPU registers in size,
|
||||
and move relocating.
|
||||
and move bitcopying.
|
||||
*/
|
||||
using error = errored_status_code<erased<system_code::value_type>>;
|
||||
using error = erased_errored_status_code<system_code::value_type>;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static_assert(sizeof(error) == 2 * sizeof(void *), "error is not exactly two pointers in size!");
|
||||
static_assert(traits::is_move_relocating<error>::value, "error is not move relocating!");
|
||||
static_assert(traits::is_move_bitcopying<error>::value, "error is not move bitcopying!");
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
@@ -0,0 +1,438 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Jun 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_ERRORED_STATUS_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_ERRORED_STATUS_CODE_HPP
|
||||
|
||||
#include "quick_status_code_from_enum.hpp"
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
/*! A `status_code` which is always a failure. The closest equivalent to
|
||||
`std::error_code`, except it cannot be modified, and is templated.
|
||||
|
||||
Differences from `status_code`:
|
||||
|
||||
- Never successful (this contract is checked on construction, if fails then it
|
||||
terminates the process).
|
||||
- Is immutable.
|
||||
*/
|
||||
template <class DomainType> class errored_status_code : public status_code<DomainType>
|
||||
{
|
||||
using _base = status_code<DomainType>;
|
||||
using _base::clear;
|
||||
using _base::success;
|
||||
|
||||
void _check()
|
||||
{
|
||||
if(_base::success())
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
//! The type of the domain.
|
||||
using typename _base::domain_type;
|
||||
//! The type of the error code.
|
||||
using typename _base::value_type;
|
||||
//! The type of a reference to a message string.
|
||||
using typename _base::string_ref;
|
||||
|
||||
//! Default constructor.
|
||||
errored_status_code() = default;
|
||||
//! Copy constructor.
|
||||
errored_status_code(const errored_status_code &) = default;
|
||||
//! Move constructor.
|
||||
errored_status_code(errored_status_code &&) = default; // NOLINT
|
||||
//! Copy assignment.
|
||||
errored_status_code &operator=(const errored_status_code &) = default;
|
||||
//! Move assignment.
|
||||
errored_status_code &operator=(errored_status_code &&) = default; // NOLINT
|
||||
~errored_status_code() = default;
|
||||
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(const _base &o) noexcept(std::is_nothrow_copy_constructible<_base>::value)
|
||||
: _base(o)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(_base &&o) noexcept(std::is_nothrow_move_constructible<_base>::value)
|
||||
: _base(static_cast<_base &&>(o))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH STATUS_CODE *****/
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(
|
||||
class T, class... Args, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<T, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!std::is_same<typename std::decay<T>::type, errored_status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, in_place_t>::value // not in_place_t
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<errored_status_code, MakeStatusCodeResult>::value)) // ADLed status code is compatible
|
||||
errored_status_code(T &&v, Args &&...args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: errored_status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
|
||||
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Enum, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type) // Enumeration has been activated
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible<errored_status_code, QuickStatusCodeType>::value)) // Its status code is compatible
|
||||
errored_status_code(Enum &&v) noexcept(std::is_nothrow_constructible<errored_status_code, QuickStatusCodeType>::value) // NOLINT
|
||||
: errored_status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit in-place construction.
|
||||
template <class... Args>
|
||||
explicit errored_status_code(in_place_t _, Args &&...args) noexcept(std::is_nothrow_constructible<value_type, Args &&...>::value)
|
||||
: _base(_, static_cast<Args &&>(args)...)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit in-place construction from initialiser list.
|
||||
template <class T, class... Args>
|
||||
explicit errored_status_code(in_place_t _, std::initializer_list<T> il,
|
||||
Args &&...args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<T>, Args &&...>::value)
|
||||
: _base(_, il, static_cast<Args &&>(args)...)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit copy construction from a `value_type`.
|
||||
explicit errored_status_code(const value_type &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: _base(v)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicit move construction from a `value_type`.
|
||||
explicit errored_status_code(value_type &&v) noexcept(std::is_nothrow_move_constructible<value_type>::value)
|
||||
: _base(static_cast<value_type &&>(v))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
/*! Explicit construction from an erased status code. Available only if
|
||||
`value_type` is trivially copyable or move bitcopying, and `sizeof(status_code) <= sizeof(status_code<erased<>>)`.
|
||||
Does not check if domains are equal.
|
||||
*/
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class ErasedType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<domain_type, detail::erased<ErasedType>>::value))
|
||||
explicit errored_status_code(const status_code<detail::erased<ErasedType>> &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: errored_status_code(detail::erasure_cast<value_type>(v.value())) // NOLINT
|
||||
{
|
||||
assert(v.domain() == this->domain()); // NOLINT
|
||||
_check();
|
||||
}
|
||||
|
||||
//! Always false (including at compile time), as errored status codes are never successful.
|
||||
constexpr bool success() const noexcept { return false; }
|
||||
//! Return a const reference to the `value_type`.
|
||||
constexpr const value_type &value() const &noexcept { return this->_value; }
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class DomainType> struct is_move_bitcopying<errored_status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = is_move_bitcopying<typename DomainType::value_type>::value;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
template <class ErasedType> class errored_status_code<detail::erased<ErasedType>> : public status_code<detail::erased<ErasedType>>
|
||||
{
|
||||
using _base = status_code<detail::erased<ErasedType>>;
|
||||
using _base::success;
|
||||
|
||||
void _check()
|
||||
{
|
||||
if(_base::success())
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
using domain_type = typename _base::domain_type;
|
||||
using value_type = typename _base::value_type;
|
||||
using string_ref = typename _base::string_ref;
|
||||
|
||||
//! Default construction to empty
|
||||
errored_status_code() = default;
|
||||
//! Copy constructor
|
||||
errored_status_code(const errored_status_code &) = default;
|
||||
//! Move constructor
|
||||
errored_status_code(errored_status_code &&) = default; // NOLINT
|
||||
//! Copy assignment
|
||||
errored_status_code &operator=(const errored_status_code &) = default;
|
||||
//! Move assignment
|
||||
errored_status_code &operator=(errored_status_code &&) = default; // NOLINT
|
||||
~errored_status_code() = default;
|
||||
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(const _base &o) noexcept(std::is_nothrow_copy_constructible<_base>::value)
|
||||
: _base(o)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Explicitly construct from any similarly erased status code
|
||||
explicit errored_status_code(_base &&o) noexcept(std::is_nothrow_move_constructible<_base>::value)
|
||||
: _base(static_cast<_base &&>(o))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH STATUS_CODE *****/
|
||||
//! Implicit copy construction from any other status code if its value type is trivially copyable, it would fit into our storage, and it is not an erased
|
||||
//! status code.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<detail::erased<ErasedType>, DomainType>::value),
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!detail::is_erased_status_code<status_code<typename std::decay<DomainType>::type>>::value))
|
||||
errored_status_code(const status_code<DomainType> &v) noexcept
|
||||
: _base(v) // NOLINT
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Implicit copy construction from any other status code if its value type is trivially copyable and it would fit into our storage, and it is not an erased
|
||||
//! status code.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<detail::erased<ErasedType>, DomainType>::value),
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!detail::is_erased_status_code<status_code<typename std::decay<DomainType>::type>>::value))
|
||||
errored_status_code(const errored_status_code<DomainType> &v) noexcept
|
||||
: _base(static_cast<const status_code<DomainType> &>(v)) // NOLINT
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Implicit move construction from any other status code if its value type is trivially copyable or move bitcopying and it would fit into our storage
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<detail::erased<ErasedType>, DomainType>::value))
|
||||
errored_status_code(status_code<DomainType> &&v) noexcept
|
||||
: _base(static_cast<status_code<DomainType> &&>(v)) // NOLINT
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Implicit move construction from any other status code if its value type is trivially copyable or move bitcopying and it would fit into our storage
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<detail::erased<ErasedType>, DomainType>::value))
|
||||
errored_status_code(errored_status_code<DomainType> &&v) noexcept
|
||||
: _base(static_cast<status_code<DomainType> &&>(v)) // NOLINT
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(
|
||||
class T, class... Args, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<T, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!std::is_same<typename std::decay<T>::type, errored_status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, value_type>::value // not copy/move of value type
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<errored_status_code, MakeStatusCodeResult>::value)) // ADLed status code is compatible
|
||||
errored_status_code(T &&v, Args &&...args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: errored_status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Enum, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type) // Enumeration has been activated
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible<errored_status_code, QuickStatusCodeType>::value)) // Its status code is compatible
|
||||
errored_status_code(Enum &&v) noexcept(std::is_nothrow_constructible<errored_status_code, QuickStatusCodeType>::value) // NOLINT
|
||||
: errored_status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
|
||||
{
|
||||
_check();
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
//! Explicit copy construction from an unknown status code. Note that this will be empty if its value type is not trivially copyable or would not fit into our
|
||||
//! storage or the source domain's `_do_erased_copy()` refused the copy.
|
||||
explicit errored_status_code(const status_code<void> &v) // NOLINT
|
||||
: _base(v)
|
||||
{
|
||||
_check();
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Always false (including at compile time), as errored status codes are never successful.
|
||||
constexpr bool success() const noexcept { return false; }
|
||||
//! Return the erased `value_type` by value.
|
||||
constexpr value_type value() const noexcept { return this->_value; }
|
||||
};
|
||||
/*! An erased type specialisation of `errored_status_code<D>`.
|
||||
Available only if `ErasedType` satisfies `traits::is_move_bitcopying<ErasedType>::value`.
|
||||
*/
|
||||
template <class ErasedType> using erased_errored_status_code = errored_status_code<detail::erased<ErasedType>>;
|
||||
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class ErasedType> struct is_move_bitcopying<errored_status_code<detail::erased<ErasedType>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2>
|
||||
inline bool operator==(const errored_status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator==(const status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator==(const errored_status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return static_cast<const status_code<DomainType1> &>(a).equivalent(b);
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2>
|
||||
inline bool operator!=(const errored_status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator!=(const status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !a.equivalent(static_cast<const status_code<DomainType2> &>(b));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2> inline bool operator!=(const errored_status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !static_cast<const status_code<DomainType1> &>(a).equivalent(b);
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
inline bool operator==(const errored_status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
inline bool operator==(const T &a, const errored_status_code<DomainType1> &b)
|
||||
{
|
||||
return b.equivalent(make_status_code(a));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
inline bool operator!=(const errored_status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return !a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
inline bool operator!=(const T &a, const errored_status_code<DomainType1> &b)
|
||||
{
|
||||
return !b.equivalent(make_status_code(a));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
|
||||
template <class DomainType1, class T, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
inline bool operator==(const errored_status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return a.equivalent(QuickStatusCodeType(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
|
||||
template <class T, class DomainType1, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
inline bool operator==(const T &a, const errored_status_code<DomainType1> &b)
|
||||
{
|
||||
return b.equivalent(QuickStatusCodeType(a));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
|
||||
template <class DomainType1, class T, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
inline bool operator!=(const errored_status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return !a.equivalent(QuickStatusCodeType(b));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
|
||||
template <class T, class DomainType1, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
inline bool operator!=(const T &a, const errored_status_code<DomainType1> &b)
|
||||
{
|
||||
return !b.equivalent(QuickStatusCodeType(a));
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T> struct is_errored_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_errored_status_code<errored_status_code<T>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <class T> struct is_erased_errored_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_erased_errored_status_code<errored_status_code<erased<T>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
//! Trait returning true if the type is an errored status code.
|
||||
template <class T> struct is_errored_status_code
|
||||
{
|
||||
static constexpr bool value =
|
||||
detail::is_errored_status_code<typename std::decay<T>::type>::value || detail::is_erased_errored_status_code<typename std::decay<T>::type>::value;
|
||||
};
|
||||
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,492 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP
|
||||
|
||||
#include "status_error.hpp"
|
||||
|
||||
#include <cerrno> // for error constants
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
//! The generic error coding (POSIX)
|
||||
enum class errc : int
|
||||
{
|
||||
success = 0,
|
||||
unknown = -1,
|
||||
|
||||
address_family_not_supported = EAFNOSUPPORT,
|
||||
address_in_use = EADDRINUSE,
|
||||
address_not_available = EADDRNOTAVAIL,
|
||||
already_connected = EISCONN,
|
||||
argument_list_too_long = E2BIG,
|
||||
argument_out_of_domain = EDOM,
|
||||
bad_address = EFAULT,
|
||||
bad_file_descriptor = EBADF,
|
||||
bad_message = EBADMSG,
|
||||
broken_pipe = EPIPE,
|
||||
connection_aborted = ECONNABORTED,
|
||||
connection_already_in_progress = EALREADY,
|
||||
connection_refused = ECONNREFUSED,
|
||||
connection_reset = ECONNRESET,
|
||||
cross_device_link = EXDEV,
|
||||
destination_address_required = EDESTADDRREQ,
|
||||
device_or_resource_busy = EBUSY,
|
||||
directory_not_empty = ENOTEMPTY,
|
||||
executable_format_error = ENOEXEC,
|
||||
file_exists = EEXIST,
|
||||
file_too_large = EFBIG,
|
||||
filename_too_long = ENAMETOOLONG,
|
||||
function_not_supported = ENOSYS,
|
||||
host_unreachable = EHOSTUNREACH,
|
||||
identifier_removed = EIDRM,
|
||||
illegal_byte_sequence = EILSEQ,
|
||||
inappropriate_io_control_operation = ENOTTY,
|
||||
interrupted = EINTR,
|
||||
invalid_argument = EINVAL,
|
||||
invalid_seek = ESPIPE,
|
||||
io_error = EIO,
|
||||
is_a_directory = EISDIR,
|
||||
message_size = EMSGSIZE,
|
||||
network_down = ENETDOWN,
|
||||
network_reset = ENETRESET,
|
||||
network_unreachable = ENETUNREACH,
|
||||
no_buffer_space = ENOBUFS,
|
||||
no_child_process = ECHILD,
|
||||
no_link = ENOLINK,
|
||||
no_lock_available = ENOLCK,
|
||||
no_message = ENOMSG,
|
||||
no_protocol_option = ENOPROTOOPT,
|
||||
no_space_on_device = ENOSPC,
|
||||
no_stream_resources = ENOSR,
|
||||
no_such_device_or_address = ENXIO,
|
||||
no_such_device = ENODEV,
|
||||
no_such_file_or_directory = ENOENT,
|
||||
no_such_process = ESRCH,
|
||||
not_a_directory = ENOTDIR,
|
||||
not_a_socket = ENOTSOCK,
|
||||
not_a_stream = ENOSTR,
|
||||
not_connected = ENOTCONN,
|
||||
not_enough_memory = ENOMEM,
|
||||
not_supported = ENOTSUP,
|
||||
operation_canceled = ECANCELED,
|
||||
operation_in_progress = EINPROGRESS,
|
||||
operation_not_permitted = EPERM,
|
||||
operation_not_supported = EOPNOTSUPP,
|
||||
operation_would_block = EWOULDBLOCK,
|
||||
owner_dead = EOWNERDEAD,
|
||||
permission_denied = EACCES,
|
||||
protocol_error = EPROTO,
|
||||
protocol_not_supported = EPROTONOSUPPORT,
|
||||
read_only_file_system = EROFS,
|
||||
resource_deadlock_would_occur = EDEADLK,
|
||||
resource_unavailable_try_again = EAGAIN,
|
||||
result_out_of_range = ERANGE,
|
||||
state_not_recoverable = ENOTRECOVERABLE,
|
||||
stream_timeout = ETIME,
|
||||
text_file_busy = ETXTBSY,
|
||||
timed_out = ETIMEDOUT,
|
||||
too_many_files_open_in_system = ENFILE,
|
||||
too_many_files_open = EMFILE,
|
||||
too_many_links = EMLINK,
|
||||
too_many_symbolic_link_levels = ELOOP,
|
||||
value_too_large = EOVERFLOW,
|
||||
wrong_protocol_type = EPROTOTYPE
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline const char *generic_code_message(errc code) noexcept
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case errc::success:
|
||||
return "Success";
|
||||
case errc::address_family_not_supported:
|
||||
return "Address family not supported by protocol";
|
||||
case errc::address_in_use:
|
||||
return "Address already in use";
|
||||
case errc::address_not_available:
|
||||
return "Cannot assign requested address";
|
||||
case errc::already_connected:
|
||||
return "Transport endpoint is already connected";
|
||||
case errc::argument_list_too_long:
|
||||
return "Argument list too long";
|
||||
case errc::argument_out_of_domain:
|
||||
return "Numerical argument out of domain";
|
||||
case errc::bad_address:
|
||||
return "Bad address";
|
||||
case errc::bad_file_descriptor:
|
||||
return "Bad file descriptor";
|
||||
case errc::bad_message:
|
||||
return "Bad message";
|
||||
case errc::broken_pipe:
|
||||
return "Broken pipe";
|
||||
case errc::connection_aborted:
|
||||
return "Software caused connection abort";
|
||||
case errc::connection_already_in_progress:
|
||||
return "Operation already in progress";
|
||||
case errc::connection_refused:
|
||||
return "Connection refused";
|
||||
case errc::connection_reset:
|
||||
return "Connection reset by peer";
|
||||
case errc::cross_device_link:
|
||||
return "Invalid cross-device link";
|
||||
case errc::destination_address_required:
|
||||
return "Destination address required";
|
||||
case errc::device_or_resource_busy:
|
||||
return "Device or resource busy";
|
||||
case errc::directory_not_empty:
|
||||
return "Directory not empty";
|
||||
case errc::executable_format_error:
|
||||
return "Exec format error";
|
||||
case errc::file_exists:
|
||||
return "File exists";
|
||||
case errc::file_too_large:
|
||||
return "File too large";
|
||||
case errc::filename_too_long:
|
||||
return "File name too long";
|
||||
case errc::function_not_supported:
|
||||
return "Function not implemented";
|
||||
case errc::host_unreachable:
|
||||
return "No route to host";
|
||||
case errc::identifier_removed:
|
||||
return "Identifier removed";
|
||||
case errc::illegal_byte_sequence:
|
||||
return "Invalid or incomplete multibyte or wide character";
|
||||
case errc::inappropriate_io_control_operation:
|
||||
return "Inappropriate ioctl for device";
|
||||
case errc::interrupted:
|
||||
return "Interrupted system call";
|
||||
case errc::invalid_argument:
|
||||
return "Invalid argument";
|
||||
case errc::invalid_seek:
|
||||
return "Illegal seek";
|
||||
case errc::io_error:
|
||||
return "Input/output error";
|
||||
case errc::is_a_directory:
|
||||
return "Is a directory";
|
||||
case errc::message_size:
|
||||
return "Message too long";
|
||||
case errc::network_down:
|
||||
return "Network is down";
|
||||
case errc::network_reset:
|
||||
return "Network dropped connection on reset";
|
||||
case errc::network_unreachable:
|
||||
return "Network is unreachable";
|
||||
case errc::no_buffer_space:
|
||||
return "No buffer space available";
|
||||
case errc::no_child_process:
|
||||
return "No child processes";
|
||||
case errc::no_link:
|
||||
return "Link has been severed";
|
||||
case errc::no_lock_available:
|
||||
return "No locks available";
|
||||
case errc::no_message:
|
||||
return "No message of desired type";
|
||||
case errc::no_protocol_option:
|
||||
return "Protocol not available";
|
||||
case errc::no_space_on_device:
|
||||
return "No space left on device";
|
||||
case errc::no_stream_resources:
|
||||
return "Out of streams resources";
|
||||
case errc::no_such_device_or_address:
|
||||
return "No such device or address";
|
||||
case errc::no_such_device:
|
||||
return "No such device";
|
||||
case errc::no_such_file_or_directory:
|
||||
return "No such file or directory";
|
||||
case errc::no_such_process:
|
||||
return "No such process";
|
||||
case errc::not_a_directory:
|
||||
return "Not a directory";
|
||||
case errc::not_a_socket:
|
||||
return "Socket operation on non-socket";
|
||||
case errc::not_a_stream:
|
||||
return "Device not a stream";
|
||||
case errc::not_connected:
|
||||
return "Transport endpoint is not connected";
|
||||
case errc::not_enough_memory:
|
||||
return "Cannot allocate memory";
|
||||
#if ENOTSUP != EOPNOTSUPP
|
||||
case errc::not_supported:
|
||||
return "Operation not supported";
|
||||
#endif
|
||||
case errc::operation_canceled:
|
||||
return "Operation canceled";
|
||||
case errc::operation_in_progress:
|
||||
return "Operation now in progress";
|
||||
case errc::operation_not_permitted:
|
||||
return "Operation not permitted";
|
||||
case errc::operation_not_supported:
|
||||
return "Operation not supported";
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
case errc::operation_would_block:
|
||||
return "Resource temporarily unavailable";
|
||||
#endif
|
||||
case errc::owner_dead:
|
||||
return "Owner died";
|
||||
case errc::permission_denied:
|
||||
return "Permission denied";
|
||||
case errc::protocol_error:
|
||||
return "Protocol error";
|
||||
case errc::protocol_not_supported:
|
||||
return "Protocol not supported";
|
||||
case errc::read_only_file_system:
|
||||
return "Read-only file system";
|
||||
case errc::resource_deadlock_would_occur:
|
||||
return "Resource deadlock avoided";
|
||||
case errc::resource_unavailable_try_again:
|
||||
return "Resource temporarily unavailable";
|
||||
case errc::result_out_of_range:
|
||||
return "Numerical result out of range";
|
||||
case errc::state_not_recoverable:
|
||||
return "State not recoverable";
|
||||
case errc::stream_timeout:
|
||||
return "Timer expired";
|
||||
case errc::text_file_busy:
|
||||
return "Text file busy";
|
||||
case errc::timed_out:
|
||||
return "Connection timed out";
|
||||
case errc::too_many_files_open_in_system:
|
||||
return "Too many open files in system";
|
||||
case errc::too_many_files_open:
|
||||
return "Too many open files";
|
||||
case errc::too_many_links:
|
||||
return "Too many links";
|
||||
case errc::too_many_symbolic_link_levels:
|
||||
return "Too many levels of symbolic links";
|
||||
case errc::value_too_large:
|
||||
return "Value too large for defined data type";
|
||||
case errc::wrong_protocol_type:
|
||||
return "Protocol wrong type for socket";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/*! The implementation of the domain for generic status codes, those mapped by `errc` (POSIX).
|
||||
*/
|
||||
class _generic_code_domain : public status_code_domain
|
||||
{
|
||||
template <class> friend class status_code;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
|
||||
public:
|
||||
//! The value type of the generic code, which is an `errc` as per POSIX.
|
||||
using value_type = errc;
|
||||
using string_ref = _base::string_ref;
|
||||
|
||||
public:
|
||||
//! Default constructor
|
||||
constexpr explicit _generic_code_domain(typename _base::unique_id_type id = 0x746d6354f4f733e9) noexcept
|
||||
: _base(id)
|
||||
{
|
||||
}
|
||||
_generic_code_domain(const _generic_code_domain &) = default;
|
||||
_generic_code_domain(_generic_code_domain &&) = default;
|
||||
_generic_code_domain &operator=(const _generic_code_domain &) = default;
|
||||
_generic_code_domain &operator=(_generic_code_domain &&) = default;
|
||||
~_generic_code_domain() = default;
|
||||
|
||||
//! Constexpr singleton getter. Returns the constexpr generic_code_domain variable.
|
||||
static inline constexpr const _generic_code_domain &get();
|
||||
|
||||
virtual _base::string_ref name() const noexcept override { return string_ref("generic domain"); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const generic_code &>(code).value() != errc::success; // NOLINT
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this); // NOLINT
|
||||
const auto &c1 = static_cast<const generic_code &>(code1); // NOLINT
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
|
||||
return c1.value() == c2.value();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const generic_code &>(code); // NOLINT
|
||||
}
|
||||
virtual _base::string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const generic_code &>(code); // NOLINT
|
||||
return string_ref(detail::generic_code_message(c.value()));
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const generic_code &>(code); // NOLINT
|
||||
throw status_error<_generic_code_domain>(c);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
//! A specialisation of `status_error` for the generic code domain.
|
||||
using generic_error = status_error<_generic_code_domain>;
|
||||
//! A constexpr source variable for the generic code domain, which is that of `errc` (POSIX). Returned by `_generic_code_domain::get()`.
|
||||
constexpr _generic_code_domain generic_code_domain;
|
||||
inline constexpr const _generic_code_domain &_generic_code_domain::get()
|
||||
{
|
||||
return generic_code_domain;
|
||||
}
|
||||
// Enable implicit construction of generic_code from errc
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline generic_code make_status_code(errc c) noexcept
|
||||
{
|
||||
return generic_code(in_place, c);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
|
||||
template <class T> inline BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 bool status_code<void>::equivalent(const status_code<T> &o) const noexcept
|
||||
{
|
||||
if(_domain && o._domain)
|
||||
{
|
||||
if(_domain->_do_equivalent(*this, o))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(o._domain->_do_equivalent(o, *this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
generic_code c1 = o._domain->_generic_code(o);
|
||||
if(c1.value() != errc::unknown && _domain->_do_equivalent(*this, c1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
generic_code c2 = _domain->_generic_code(*this);
|
||||
if(c2.value() != errc::unknown && o._domain->_do_equivalent(o, c2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If we are both empty, we are equivalent, otherwise not equivalent
|
||||
return (!_domain && !o._domain);
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return a.equivalent(b);
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()`.
|
||||
template <class DomainType1, class DomainType2>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
|
||||
{
|
||||
return !a.equivalent(b);
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b)
|
||||
{
|
||||
return b.equivalent(make_status_code(a));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return !a.equivalent(make_status_code(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b)
|
||||
{
|
||||
return !b.equivalent(make_status_code(a));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
|
||||
template <class DomainType1, class T, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return a.equivalent(QuickStatusCodeType(b));
|
||||
}
|
||||
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
|
||||
template <class T, class DomainType1, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b)
|
||||
{
|
||||
return b.equivalent(QuickStatusCodeType(a));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
|
||||
template <class DomainType1, class T, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b)
|
||||
{
|
||||
return !a.equivalent(QuickStatusCodeType(b));
|
||||
}
|
||||
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
|
||||
template <class T, class DomainType1, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
|
||||
>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b)
|
||||
{
|
||||
return !b.equivalent(QuickStatusCodeType(a));
|
||||
}
|
||||
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2020-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Jan 2020
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_GETADDRINFO_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_GETADDRINFO_CODE_HPP
|
||||
|
||||
#include "quick_status_code_from_enum.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#error Not available for Microsoft Windows
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
class _getaddrinfo_code_domain;
|
||||
//! A getaddrinfo error code, those returned by `getaddrinfo()`.
|
||||
using getaddrinfo_code = status_code<_getaddrinfo_code_domain>;
|
||||
//! A specialisation of `status_error` for the `getaddrinfo()` error code domain.
|
||||
using getaddrinfo_error = status_error<_getaddrinfo_code_domain>;
|
||||
|
||||
/*! The implementation of the domain for `getaddrinfo()` error codes, those returned by `getaddrinfo()`.
|
||||
*/
|
||||
class _getaddrinfo_code_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
|
||||
public:
|
||||
//! The value type of the `getaddrinfo()` code, which is an `int`
|
||||
using value_type = int;
|
||||
using _base::string_ref;
|
||||
|
||||
//! Default constructor
|
||||
constexpr explicit _getaddrinfo_code_domain(typename _base::unique_id_type id = 0x5b24b2de470ff7b6) noexcept
|
||||
: _base(id)
|
||||
{
|
||||
}
|
||||
_getaddrinfo_code_domain(const _getaddrinfo_code_domain &) = default;
|
||||
_getaddrinfo_code_domain(_getaddrinfo_code_domain &&) = default;
|
||||
_getaddrinfo_code_domain &operator=(const _getaddrinfo_code_domain &) = default;
|
||||
_getaddrinfo_code_domain &operator=(_getaddrinfo_code_domain &&) = default;
|
||||
~_getaddrinfo_code_domain() = default;
|
||||
|
||||
//! Constexpr singleton getter. Returns constexpr getaddrinfo_code_domain variable.
|
||||
static inline constexpr const _getaddrinfo_code_domain &get();
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref("getaddrinfo() domain"); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const getaddrinfo_code &>(code).value() != 0; // NOLINT
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this); // NOLINT
|
||||
const auto &c1 = static_cast<const getaddrinfo_code &>(code1); // NOLINT
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const getaddrinfo_code &>(code2); // NOLINT
|
||||
return c1.value() == c2.value();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const getaddrinfo_code &>(code); // NOLINT
|
||||
switch(c.value())
|
||||
{
|
||||
#ifdef EAI_ADDRFAMILY
|
||||
case EAI_ADDRFAMILY:
|
||||
return errc::no_such_device_or_address;
|
||||
#endif
|
||||
case EAI_FAIL:
|
||||
return errc::io_error;
|
||||
case EAI_MEMORY:
|
||||
return errc::not_enough_memory;
|
||||
#ifdef EAI_NODATA
|
||||
case EAI_NODATA:
|
||||
return errc::no_such_device_or_address;
|
||||
#endif
|
||||
case EAI_NONAME:
|
||||
return errc::no_such_device_or_address;
|
||||
#ifdef EAI_OVERFLOW
|
||||
case EAI_OVERFLOW:
|
||||
return errc::argument_list_too_long;
|
||||
#endif
|
||||
case EAI_BADFLAGS: // fallthrough
|
||||
case EAI_SERVICE:
|
||||
return errc::invalid_argument;
|
||||
case EAI_FAMILY: // fallthrough
|
||||
case EAI_SOCKTYPE:
|
||||
return errc::operation_not_supported;
|
||||
case EAI_AGAIN: // fallthrough
|
||||
case EAI_SYSTEM:
|
||||
return errc::resource_unavailable_try_again;
|
||||
default:
|
||||
return errc::unknown;
|
||||
}
|
||||
}
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const getaddrinfo_code &>(code); // NOLINT
|
||||
return string_ref(gai_strerror(c.value()));
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const getaddrinfo_code &>(code); // NOLINT
|
||||
throw status_error<_getaddrinfo_code_domain>(c);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
//! A constexpr source variable for the `getaddrinfo()` code domain, which is that of `getaddrinfo()`. Returned by `_getaddrinfo_code_domain::get()`.
|
||||
constexpr _getaddrinfo_code_domain getaddrinfo_code_domain;
|
||||
inline constexpr const _getaddrinfo_code_domain &_getaddrinfo_code_domain::get()
|
||||
{
|
||||
return getaddrinfo_code_domain;
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,340 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2022-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Jun 2022
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_HTTP_STATUS_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_HTTP_STATUS_CODE_HPP
|
||||
|
||||
#include "status_code.hpp"
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
class _http_status_code_domain;
|
||||
//! A HTTP status code.
|
||||
using http_status_code = status_code<_http_status_code_domain>;
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> struct mixin<Base, _http_status_code_domain> : public Base
|
||||
{
|
||||
using Base::Base;
|
||||
|
||||
//! True if the HTTP status code is informational
|
||||
inline bool is_http_informational() const noexcept;
|
||||
//! True if the HTTP status code is successful
|
||||
inline bool is_http_success() const noexcept;
|
||||
//! True if the HTTP status code is redirection
|
||||
inline bool is_http_redirection() const noexcept;
|
||||
//! True if the HTTP status code is client error
|
||||
inline bool is_http_client_error() const noexcept;
|
||||
//! True if the HTTP status code is server error
|
||||
inline bool is_http_server_error() const noexcept;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
/*! The implementation of the domain for HTTP status codes.
|
||||
*/
|
||||
class _http_status_code_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
|
||||
public:
|
||||
//! The value type of the HTTP code, which is an `int`
|
||||
using value_type = int;
|
||||
using _base::string_ref;
|
||||
|
||||
//! Default constructor
|
||||
constexpr explicit _http_status_code_domain(typename _base::unique_id_type id = 0xbdb4cde88378a333ull) noexcept
|
||||
: _base(id)
|
||||
{
|
||||
}
|
||||
_http_status_code_domain(const _http_status_code_domain &) = default;
|
||||
_http_status_code_domain(_http_status_code_domain &&) = default;
|
||||
_http_status_code_domain &operator=(const _http_status_code_domain &) = default;
|
||||
_http_status_code_domain &operator=(_http_status_code_domain &&) = default;
|
||||
~_http_status_code_domain() = default;
|
||||
|
||||
//! Constexpr singleton getter. Returns constexpr http_status_code_domain variable.
|
||||
static inline constexpr const _http_status_code_domain &get();
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref("HTTP status domain"); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const http_status_code &>(code).value() >= 400; // NOLINT
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this); // NOLINT
|
||||
const auto &c1 = static_cast<const http_status_code &>(code1); // NOLINT
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const http_status_code &>(code2); // NOLINT
|
||||
return c1.value() == c2.value();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const http_status_code &>(code); // NOLINT
|
||||
switch(c.value())
|
||||
{
|
||||
case 102:
|
||||
case 202:
|
||||
return errc::operation_in_progress;
|
||||
case 400:
|
||||
return errc::invalid_argument;
|
||||
case 401:
|
||||
return errc::operation_not_permitted;
|
||||
case 403:
|
||||
return errc::permission_denied;
|
||||
case 404:
|
||||
case 410:
|
||||
return errc::no_such_file_or_directory;
|
||||
case 405:
|
||||
case 418:
|
||||
return errc::operation_not_supported;
|
||||
case 406:
|
||||
return errc::protocol_not_supported;
|
||||
case 408:
|
||||
return errc::timed_out;
|
||||
case 413:
|
||||
return errc::result_out_of_range;
|
||||
case 501:
|
||||
return errc::not_supported;
|
||||
case 503:
|
||||
return errc::resource_unavailable_try_again;
|
||||
case 504:
|
||||
return errc::timed_out;
|
||||
case 507:
|
||||
return errc::no_space_on_device;
|
||||
default:
|
||||
return errc::unknown;
|
||||
}
|
||||
}
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const http_status_code &>(code); // NOLINT
|
||||
return string_ref(
|
||||
[&]() -> const char *
|
||||
{
|
||||
switch(c.value())
|
||||
{
|
||||
case 100:
|
||||
return "Continue";
|
||||
case 101:
|
||||
return "Switching Protocols";
|
||||
case 102:
|
||||
return "Processing";
|
||||
case 103:
|
||||
return "Early Hints";
|
||||
case 200:
|
||||
return "OK";
|
||||
case 201:
|
||||
return "Created";
|
||||
case 202:
|
||||
return "Accepted";
|
||||
case 203:
|
||||
return "Non-Authoritative Information";
|
||||
case 204:
|
||||
return "No Content";
|
||||
case 205:
|
||||
return "Reset Content";
|
||||
case 206:
|
||||
return "Partial Content";
|
||||
case 207:
|
||||
return "Multi-Status";
|
||||
case 208:
|
||||
return "Already Reported";
|
||||
case 209:
|
||||
return "IM Used";
|
||||
case 300:
|
||||
return "Multiple Choices";
|
||||
case 301:
|
||||
return "Moved Permanently";
|
||||
case 302:
|
||||
return "Found";
|
||||
case 303:
|
||||
return "See Other";
|
||||
case 304:
|
||||
return "Not Modified";
|
||||
case 305:
|
||||
return "Use Proxy";
|
||||
case 306:
|
||||
return "Switch Proxy";
|
||||
case 307:
|
||||
return "Temporary Redirect";
|
||||
case 308:
|
||||
return "Permanent Redirect";
|
||||
case 400:
|
||||
return "Bad Request";
|
||||
case 401:
|
||||
return "Unauthorized";
|
||||
case 402:
|
||||
return "Payment Required";
|
||||
case 403:
|
||||
return "Forbidden";
|
||||
case 404:
|
||||
return "Not Found";
|
||||
case 405:
|
||||
return "Method Not Allowed";
|
||||
case 406:
|
||||
return "Not Acceptable";
|
||||
case 407:
|
||||
return "Proxy Authentication Required";
|
||||
case 408:
|
||||
return "Request Timeout";
|
||||
case 409:
|
||||
return "Conflict";
|
||||
case 410:
|
||||
return "Gone";
|
||||
case 411:
|
||||
return "Length Required";
|
||||
case 412:
|
||||
return "Precondition Failed";
|
||||
case 413:
|
||||
return "Payload Too Large";
|
||||
case 414:
|
||||
return "URI Too Long";
|
||||
case 415:
|
||||
return "Unsupported Media Type";
|
||||
case 416:
|
||||
return "Range Not Satisfiable";
|
||||
case 417:
|
||||
return "Expectation Failed";
|
||||
case 418:
|
||||
return "I'm a teapot";
|
||||
case 421:
|
||||
return "Misdirected Request";
|
||||
case 422:
|
||||
return "Unprocessable Entity";
|
||||
case 423:
|
||||
return "Locked";
|
||||
case 424:
|
||||
return "Failed Dependency";
|
||||
case 425:
|
||||
return "Too Early";
|
||||
case 426:
|
||||
return "Upgrade Required";
|
||||
case 428:
|
||||
return "Precondition Required";
|
||||
case 429:
|
||||
return "Too Many Requests";
|
||||
case 431:
|
||||
return "Request Header Fields Too Large";
|
||||
case 451:
|
||||
return "Unavailable For Legal Reasons";
|
||||
case 500:
|
||||
return "Internal Server Error";
|
||||
case 501:
|
||||
return "Not Implemented";
|
||||
case 502:
|
||||
return "Bad Gateway";
|
||||
case 503:
|
||||
return "Service Unavailable";
|
||||
case 504:
|
||||
return "Gateway Timeout";
|
||||
case 505:
|
||||
return "HTTP Version Not Supported";
|
||||
case 506:
|
||||
return "Variant Also Negotiates";
|
||||
case 507:
|
||||
return "Insufficient Storage";
|
||||
case 508:
|
||||
return "Loop Detected";
|
||||
case 510:
|
||||
return "Not Extended";
|
||||
case 511:
|
||||
return "Network Authentication Required";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}());
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const http_status_code &>(code); // NOLINT
|
||||
throw status_error<_http_status_code_domain>(c);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
//! A constexpr source variable for the `getaddrinfo()` code domain, which is that of `getaddrinfo()`. Returned by `_http_status_code_domain::get()`.
|
||||
constexpr _http_status_code_domain http_status_code_domain;
|
||||
inline constexpr const _http_status_code_domain &_http_status_code_domain::get()
|
||||
{
|
||||
return http_status_code_domain;
|
||||
}
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> inline bool mixin<Base, _http_status_code_domain>::is_http_informational() const noexcept
|
||||
{
|
||||
const auto &c = static_cast<const http_status_code *>(this)->value();
|
||||
return c >= 100 && c < 200;
|
||||
}
|
||||
template <class Base> inline bool mixin<Base, _http_status_code_domain>::is_http_success() const noexcept
|
||||
{
|
||||
const auto &c = static_cast<const http_status_code *>(this)->value();
|
||||
return c >= 200 && c < 300;
|
||||
}
|
||||
template <class Base> inline bool mixin<Base, _http_status_code_domain>::is_http_redirection() const noexcept
|
||||
{
|
||||
const auto &c = static_cast<const http_status_code *>(this)->value();
|
||||
return c >= 300 && c < 400;
|
||||
}
|
||||
template <class Base> inline bool mixin<Base, _http_status_code_domain>::is_http_client_error() const noexcept
|
||||
{
|
||||
const auto &c = static_cast<const http_status_code *>(this)->value();
|
||||
return c >= 400 && c < 500;
|
||||
}
|
||||
template <class Base> inline bool mixin<Base, _http_status_code_domain>::is_http_server_error() const noexcept
|
||||
{
|
||||
const auto &c = static_cast<const http_status_code *>(this)->value();
|
||||
return c >= 500 && c < 600;
|
||||
}
|
||||
} // namespace mixins
|
||||
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -33,15 +33,17 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "error.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
/*! Print the status code to a `std::ostream &`.
|
||||
Requires that `DomainType::value_type` implements an `operator<<` overload for `std::ostream`.
|
||||
*/
|
||||
template <class DomainType, //
|
||||
typename std::enable_if<std::is_same<std::ostream, typename std::decay<decltype(std::declval<std::ostream>() << std::declval<typename status_code<DomainType>::value_type>())>::type>::value, bool>::type = true>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(
|
||||
std::is_same<std::ostream,
|
||||
typename std::decay<decltype(std::declval<std::ostream>() << std::declval<typename status_code<DomainType>::value_type>())>::type>::value))
|
||||
inline std::ostream &operator<<(std::ostream &s, const status_code<DomainType> &v)
|
||||
{
|
||||
if(v.empty())
|
||||
@@ -51,26 +53,33 @@ inline std::ostream &operator<<(std::ostream &s, const status_code<DomainType> &
|
||||
return s << v.domain().name().c_str() << ": " << v.value();
|
||||
}
|
||||
|
||||
/*! Print a status code domain's `string_ref` to a `std::ostream &`.
|
||||
*/
|
||||
inline std::ostream &operator<<(std::ostream &s, const status_code_domain::string_ref &v)
|
||||
{
|
||||
return s << v.c_str();
|
||||
}
|
||||
|
||||
/*! Print the erased status code to a `std::ostream &`.
|
||||
*/
|
||||
template <class ErasedType> inline std::ostream &operator<<(std::ostream &s, const status_code<erased<ErasedType>> &v)
|
||||
*/
|
||||
template <class ErasedType> inline std::ostream &operator<<(std::ostream &s, const status_code<detail::erased<ErasedType>> &v)
|
||||
{
|
||||
if(v.empty())
|
||||
{
|
||||
return s << "(empty)";
|
||||
}
|
||||
return s << v.domain().name().c_str() << ": " << v.message().c_str();
|
||||
return s << v.domain().name() << ": " << v.message();
|
||||
}
|
||||
|
||||
/*! Print the generic code to a `std::ostream &`.
|
||||
*/
|
||||
*/
|
||||
inline std::ostream &operator<<(std::ostream &s, const generic_code &v)
|
||||
{
|
||||
if(v.empty())
|
||||
{
|
||||
return s << "(empty)";
|
||||
}
|
||||
return s << v.domain().name().c_str() << ": " << v.message().c_str();
|
||||
return s << v.domain().name() << ": " << v.message();
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
@@ -0,0 +1,256 @@
|
||||
/* Pointer to a SG14 status_code
|
||||
(C) 2018 - 2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Sep 2018
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NESTED_STATUS_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_NESTED_STATUS_CODE_HPP
|
||||
|
||||
#include "quick_status_code_from_enum.hpp"
|
||||
|
||||
#include <memory> // for allocator
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class StatusCode, class Allocator> class indirecting_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
using _base = status_code_domain;
|
||||
|
||||
public:
|
||||
struct payload_type
|
||||
{
|
||||
using allocator_traits = std::allocator_traits<Allocator>;
|
||||
union
|
||||
{
|
||||
char _uninit[sizeof(StatusCode)];
|
||||
StatusCode sc;
|
||||
};
|
||||
Allocator alloc;
|
||||
|
||||
payload_type(StatusCode _sc, Allocator _alloc)
|
||||
: alloc(static_cast<Allocator &&>(_alloc))
|
||||
{
|
||||
allocator_traits::construct(alloc, &sc, static_cast<StatusCode &&>(_sc));
|
||||
}
|
||||
payload_type(const payload_type &) = delete;
|
||||
payload_type(payload_type &&) = delete;
|
||||
~payload_type() { allocator_traits::destroy(alloc, &sc); }
|
||||
};
|
||||
using value_type = payload_type *;
|
||||
using payload_allocator_traits = typename payload_type::allocator_traits::template rebind_traits<payload_type>;
|
||||
using _base::string_ref;
|
||||
|
||||
constexpr indirecting_domain() noexcept
|
||||
: _base(0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id() /* unique-ish based on domain's unique id */)
|
||||
{
|
||||
}
|
||||
indirecting_domain(const indirecting_domain &) = default;
|
||||
indirecting_domain(indirecting_domain &&) = default; // NOLINT
|
||||
indirecting_domain &operator=(const indirecting_domain &) = default;
|
||||
indirecting_domain &operator=(indirecting_domain &&) = default; // NOLINT
|
||||
~indirecting_domain() = default;
|
||||
|
||||
#if __cplusplus < 201402L && !defined(_MSC_VER)
|
||||
static inline const indirecting_domain &get()
|
||||
{
|
||||
static indirecting_domain v;
|
||||
return v;
|
||||
}
|
||||
#else
|
||||
static inline constexpr const indirecting_domain &get();
|
||||
#endif
|
||||
|
||||
virtual string_ref name() const noexcept override { return typename StatusCode::domain_type().name(); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
using _mycode = status_code<indirecting_domain>;
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
return typename StatusCode::domain_type()._do_failure(c.value()->sc);
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this);
|
||||
const auto &c1 = static_cast<const _mycode &>(code1); // NOLINT
|
||||
return typename StatusCode::domain_type()._do_equivalent(c1.value()->sc, code2);
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
return typename StatusCode::domain_type()._generic_code(c.value()->sc);
|
||||
}
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
return typename StatusCode::domain_type()._do_message(c.value()->sc);
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
typename StatusCode::domain_type()._do_throw_exception(c.value()->sc);
|
||||
abort(); // suppress buggy GCC warning
|
||||
}
|
||||
#endif
|
||||
virtual bool _do_erased_copy(status_code<void> &dst, const status_code<void> &src, payload_info_t dstinfo) const override // NOLINT
|
||||
{
|
||||
// Note that dst may not have its domain set
|
||||
const auto srcinfo = payload_info();
|
||||
assert(src.domain() == *this);
|
||||
if(dstinfo.total_size < srcinfo.total_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto &d = static_cast<_mycode &>(dst); // NOLINT
|
||||
const auto &_s = static_cast<const _mycode &>(src); // NOLINT
|
||||
const payload_type &sp = *_s.value();
|
||||
typename payload_allocator_traits::template rebind_alloc<payload_type> payload_alloc(sp.alloc);
|
||||
auto *dp = payload_allocator_traits::allocate(payload_alloc, 1);
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
try
|
||||
#endif
|
||||
{
|
||||
payload_allocator_traits::construct(payload_alloc, dp, sp.sc, sp.alloc);
|
||||
new(BOOST_OUTCOME_SYSTEM_ERROR2_ADDRESS_OF(d)) _mycode(in_place, dp);
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
catch(...)
|
||||
{
|
||||
payload_allocator_traits::deallocate(payload_alloc, dp, 1);
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
virtual void _do_erased_destroy(status_code<void> &code, payload_info_t /*unused*/) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
auto &c = static_cast<_mycode &>(code); // NOLINT
|
||||
payload_type *p = c.value();
|
||||
typename payload_allocator_traits::template rebind_alloc<payload_type> payload_alloc(p->alloc);
|
||||
payload_allocator_traits::destroy(payload_alloc, p);
|
||||
payload_allocator_traits::deallocate(payload_alloc, p, 1);
|
||||
}
|
||||
};
|
||||
#if __cplusplus >= 201402L || defined(_MSC_VER)
|
||||
template <class StatusCode, class Allocator> constexpr indirecting_domain<StatusCode, Allocator> _indirecting_domain{};
|
||||
template <class StatusCode, class Allocator>
|
||||
inline constexpr const indirecting_domain<StatusCode, Allocator> &indirecting_domain<StatusCode, Allocator>::get()
|
||||
{
|
||||
return _indirecting_domain<StatusCode, Allocator>;
|
||||
}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
/*! Make an erased status code which indirects to a dynamically allocated status code,
|
||||
using the allocator `alloc`.
|
||||
|
||||
This is useful for shoehorning a rich status code with large value type into a small
|
||||
erased status code like `system_code`, with which the status code generated by this
|
||||
function is compatible. Note that this function can throw if the allocator throws.
|
||||
*/
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class Alloc = std::allocator<typename std::decay<T>::type>)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<T>::value)) //
|
||||
inline status_code<detail::erased<typename std::add_pointer<typename std::decay<T>::type>::type>> make_nested_status_code(T &&v, Alloc alloc = {})
|
||||
{
|
||||
using status_code_type = typename std::decay<T>::type;
|
||||
using domain_type = detail::indirecting_domain<status_code_type, typename std::decay<Alloc>::type>;
|
||||
using payload_allocator_traits = typename domain_type::payload_allocator_traits;
|
||||
typename payload_allocator_traits::template rebind_alloc<typename domain_type::payload_type> payload_alloc(alloc);
|
||||
auto *p = payload_allocator_traits::allocate(payload_alloc, 1);
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
try
|
||||
#endif
|
||||
{
|
||||
payload_allocator_traits::construct(payload_alloc, p, static_cast<T &&>(v), static_cast<Alloc &&>(alloc));
|
||||
return status_code<domain_type>(in_place, p);
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
catch(...)
|
||||
{
|
||||
payload_allocator_traits::deallocate(payload_alloc, p, 1);
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! If a status code refers to a `nested_status_code` which indirects to a status
|
||||
code of type `StatusCode`, return a pointer to that `StatusCode`. Otherwise return null.
|
||||
*/
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class StatusCode, class U)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<StatusCode>::value)) inline StatusCode *get_if(status_code<detail::erased<U>> *v) noexcept
|
||||
{
|
||||
if((0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id()) != v->domain().id())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
union
|
||||
{
|
||||
U value;
|
||||
StatusCode *ret;
|
||||
};
|
||||
value = v->value();
|
||||
return ret;
|
||||
}
|
||||
//! \overload Const overload
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class StatusCode, class U)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<StatusCode>::value))
|
||||
inline const StatusCode *get_if(const status_code<detail::erased<U>> *v) noexcept
|
||||
{
|
||||
if((0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id()) != v->domain().id())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
union
|
||||
{
|
||||
U value;
|
||||
const StatusCode *ret;
|
||||
};
|
||||
value = v->value();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*! If a status code refers to a `nested_status_code`, return the id of the erased
|
||||
status code's domain. Otherwise return a meaningless number.
|
||||
*/
|
||||
template <class U> inline typename status_code_domain::unique_id_type get_id(const status_code<detail::erased<U>> &v) noexcept
|
||||
{
|
||||
return 0xc44f7bdeb2cc50e9 ^ v.domain().id();
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -47,8 +47,18 @@ namespace win32
|
||||
// A Win32 HMODULE
|
||||
using HMODULE = void *;
|
||||
// Used to retrieve where the NTDLL DLL is mapped into memory
|
||||
extern "C" HMODULE __stdcall GetModuleHandleW(const wchar_t *lpModuleName);
|
||||
}
|
||||
extern HMODULE __stdcall GetModuleHandleW(const wchar_t *lpModuleName);
|
||||
#pragma comment(lib, "kernel32.lib")
|
||||
#if(defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64))
|
||||
#pragma comment(linker, "/alternatename:?GetModuleHandleW@win32@system_error2@@YAPEAXPEB_W@Z=GetModuleHandleW")
|
||||
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
|
||||
#pragma comment(linker, "/alternatename:?GetModuleHandleW@win32@system_error2@@YGPAXPB_W@Z=_GetModuleHandleW@4")
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
#pragma comment(linker, "/alternatename:?GetModuleHandleW@win32@system_error2@@YAPAXPB_W@Z=GetModuleHandleW")
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
} // namespace win32
|
||||
|
||||
class _nt_code_domain;
|
||||
//! (Windows only) A NT error code, those returned by NT kernel functions.
|
||||
@@ -57,11 +67,11 @@ using nt_code = status_code<_nt_code_domain>;
|
||||
using nt_error = status_error<_nt_code_domain>;
|
||||
|
||||
/*! (Windows only) The implementation of the domain for NT error codes, those returned by NT kernel functions.
|
||||
*/
|
||||
*/
|
||||
class _nt_code_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode> friend class detail::indirecting_domain;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
friend class _com_code_domain;
|
||||
using _base = status_code_domain;
|
||||
static int _nt_code_to_errno(win32::NTSTATUS c)
|
||||
@@ -93,7 +103,9 @@ class _nt_code_domain : public status_code_domain
|
||||
{
|
||||
wchar_t buffer[32768];
|
||||
static win32::HMODULE ntdll = win32::GetModuleHandleW(L"NTDLL.DLL");
|
||||
win32::DWORD wlen = win32::FormatMessageW(0x00000800 /*FORMAT_MESSAGE_FROM_HMODULE*/ | 0x00001000 /*FORMAT_MESSAGE_FROM_SYSTEM*/ | 0x00000200 /*FORMAT_MESSAGE_IGNORE_INSERTS*/, ntdll, c, (1 << 10) /*MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)*/, buffer, 32768, nullptr);
|
||||
win32::DWORD wlen =
|
||||
win32::FormatMessageW(0x00000800 /*FORMAT_MESSAGE_FROM_HMODULE*/ | 0x00001000 /*FORMAT_MESSAGE_FROM_SYSTEM*/ | 0x00000200 /*FORMAT_MESSAGE_IGNORE_INSERTS*/,
|
||||
ntdll, c, (1 << 10) /*MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)*/, buffer, 32768, nullptr);
|
||||
size_t allocation = wlen + (wlen >> 1);
|
||||
win32::DWORD bytes;
|
||||
if(wlen == 0)
|
||||
@@ -135,7 +147,10 @@ public:
|
||||
|
||||
public:
|
||||
//! Default constructor
|
||||
constexpr explicit _nt_code_domain(typename _base::unique_id_type id = 0x93f3b4487e4af25b) noexcept : _base(id) {}
|
||||
constexpr explicit _nt_code_domain(typename _base::unique_id_type id = 0x93f3b4487e4af25b) noexcept
|
||||
: _base(id)
|
||||
{
|
||||
}
|
||||
_nt_code_domain(const _nt_code_domain &) = default;
|
||||
_nt_code_domain(_nt_code_domain &&) = default;
|
||||
_nt_code_domain &operator=(const _nt_code_domain &) = default;
|
||||
@@ -146,6 +161,13 @@ public:
|
||||
static inline constexpr const _nt_code_domain &get();
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref("NT domain"); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -31,24 +31,57 @@ DEALINGS IN THE SOFTWARE.
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_POSIX_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_POSIX_CODE_HPP
|
||||
|
||||
#include "generic_code.hpp"
|
||||
#ifdef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
|
||||
#error <posix_code.hpp> is not includable when BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX is defined!
|
||||
#endif
|
||||
|
||||
#include "quick_status_code_from_enum.hpp"
|
||||
|
||||
#include <cstring> // for strchr and strerror_r
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
// Fix for issue #48 Issue compiling on arm-none-eabi (newlib) with GNU extensions off
|
||||
#ifdef __APPLE__
|
||||
#include <cstring>
|
||||
#elif !defined(_MSC_VER)
|
||||
namespace detail
|
||||
{
|
||||
namespace avoid_string_include
|
||||
{
|
||||
#if defined(__GLIBC__) && !defined(__UCLIBC__)
|
||||
// This returns int for non-glibc strerror_r, but glibc's is particularly weird so we retain it
|
||||
extern "C" char *strerror_r(int errnum, char *buf, size_t buflen);
|
||||
#else
|
||||
extern "C" int strerror_r(int errnum, char *buf, size_t buflen);
|
||||
#endif
|
||||
} // namespace avoid_string_include
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
class _posix_code_domain;
|
||||
//! A POSIX error code, those returned by `errno`.
|
||||
using posix_code = status_code<_posix_code_domain>;
|
||||
//! A specialisation of `status_error` for the POSIX error code domain.
|
||||
using posix_error = status_error<_posix_code_domain>;
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> struct mixin<Base, _posix_code_domain> : public Base
|
||||
{
|
||||
using Base::Base;
|
||||
|
||||
//! Returns a `posix_code` for the current value of `errno`.
|
||||
static posix_code current() noexcept;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
/*! The implementation of the domain for POSIX error codes, those returned by `errno`.
|
||||
*/
|
||||
*/
|
||||
class _posix_code_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode> friend class detail::indirecting_domain;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
|
||||
static _base::string_ref _make_string_ref(int c) noexcept
|
||||
@@ -56,17 +89,19 @@ class _posix_code_domain : public status_code_domain
|
||||
char buffer[1024] = "";
|
||||
#ifdef _WIN32
|
||||
strerror_s(buffer, sizeof(buffer), c);
|
||||
#elif defined(__linux__)
|
||||
char *s = strerror_r(c, buffer, sizeof(buffer)); // NOLINT
|
||||
#elif defined(__GLIBC__) && !defined(__UCLIBC__) // handle glibc's weird strerror_r()
|
||||
char *s = detail::avoid_string_include::strerror_r(c, buffer, sizeof(buffer)); // NOLINT
|
||||
if(s != nullptr)
|
||||
{
|
||||
strncpy(buffer, s, sizeof(buffer)); // NOLINT
|
||||
strncpy(buffer, s, sizeof(buffer) - 1); // NOLINT
|
||||
buffer[1023] = 0;
|
||||
}
|
||||
#elif !defined(__APPLE__)
|
||||
detail::avoid_string_include::strerror_r(c, buffer, sizeof(buffer));
|
||||
#else
|
||||
strerror_r(c, buffer, sizeof(buffer));
|
||||
#endif
|
||||
size_t length = strlen(buffer); // NOLINT
|
||||
size_t length = strlen(buffer); // NOLINT
|
||||
auto *p = static_cast<char *>(malloc(length + 1)); // NOLINT
|
||||
if(p == nullptr)
|
||||
{
|
||||
@@ -82,7 +117,10 @@ public:
|
||||
using _base::string_ref;
|
||||
|
||||
//! Default constructor
|
||||
constexpr explicit _posix_code_domain(typename _base::unique_id_type id = 0xa59a56fe5f310933) noexcept : _base(id) {}
|
||||
constexpr explicit _posix_code_domain(typename _base::unique_id_type id = 0xa59a56fe5f310933) noexcept
|
||||
: _base(id)
|
||||
{
|
||||
}
|
||||
_posix_code_domain(const _posix_code_domain &) = default;
|
||||
_posix_code_domain(_posix_code_domain &&) = default;
|
||||
_posix_code_domain &operator=(const _posix_code_domain &) = default;
|
||||
@@ -93,16 +131,23 @@ public:
|
||||
static inline constexpr const _posix_code_domain &get();
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref("posix domain"); } // NOLINT
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const posix_code &>(code).value() != 0; // NOLINT
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
return static_cast<const posix_code &>(code).value() != 0; // NOLINT
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this); // NOLINT
|
||||
const auto &c1 = static_cast<const posix_code &>(code1); // NOLINT
|
||||
assert(code1.domain() == *this); // NOLINT
|
||||
const auto &c1 = static_cast<const posix_code &>(code1); // NOLINT
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const posix_code &>(code2); // NOLINT
|
||||
@@ -120,21 +165,21 @@ protected:
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const posix_code &>(code); // NOLINT
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const posix_code &>(code); // NOLINT
|
||||
return generic_code(static_cast<errc>(c.value()));
|
||||
}
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const posix_code &>(code); // NOLINT
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const posix_code &>(code); // NOLINT
|
||||
return _make_string_ref(c.value());
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const posix_code &>(code); // NOLINT
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const posix_code &>(code); // NOLINT
|
||||
throw status_error<_posix_code_domain>(c);
|
||||
}
|
||||
#endif
|
||||
@@ -146,6 +191,14 @@ inline constexpr const _posix_code_domain &_posix_code_domain::get()
|
||||
return posix_code_domain;
|
||||
}
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> inline posix_code mixin<Base, _posix_code_domain>::current() noexcept
|
||||
{
|
||||
return posix_code(errno);
|
||||
}
|
||||
} // namespace mixins
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,217 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: May 2020
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_QUICK_STATUS_CODE_FROM_ENUM_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_QUICK_STATUS_CODE_FROM_ENUM_HPP
|
||||
|
||||
#include "generic_code.hpp"
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
template <class Enum> class _quick_status_code_from_enum_domain;
|
||||
//! A status code wrapping `Enum` generated from `quick_status_code_from_enum`.
|
||||
template <class Enum> using quick_status_code_from_enum_code = status_code<_quick_status_code_from_enum_domain<Enum>>;
|
||||
|
||||
//! Defaults for an implementation of `quick_status_code_from_enum<Enum>`
|
||||
template <class Enum> struct quick_status_code_from_enum_defaults
|
||||
{
|
||||
//! The type of the resulting code
|
||||
using code_type = quick_status_code_from_enum_code<Enum>;
|
||||
//! Used within `quick_status_code_from_enum` to define a mapping of enumeration value with its status code
|
||||
struct mapping
|
||||
{
|
||||
//! The enumeration type
|
||||
using enumeration_type = Enum;
|
||||
|
||||
//! The value being mapped
|
||||
const Enum value;
|
||||
//! A string representation for this enumeration value
|
||||
const char *message;
|
||||
//! A list of `errc` equivalents for this enumeration value
|
||||
const std::initializer_list<errc> code_mappings;
|
||||
};
|
||||
//! Used within `quick_status_code_from_enum` to define mixins for the status code wrapping `Enum`
|
||||
template <class Base> struct mixin : Base
|
||||
{
|
||||
using Base::Base;
|
||||
};
|
||||
};
|
||||
|
||||
/*! The implementation of the domain for status codes wrapping `Enum` generated from `quick_status_code_from_enum`.
|
||||
*/
|
||||
template <class Enum> class _quick_status_code_from_enum_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
using _src = quick_status_code_from_enum<Enum>;
|
||||
|
||||
public:
|
||||
//! The value type of the quick status code from enum
|
||||
using value_type = Enum;
|
||||
using _base::string_ref;
|
||||
|
||||
constexpr _quick_status_code_from_enum_domain()
|
||||
: status_code_domain(_src::domain_uuid, _uuid_size<detail::cstrlen(_src::domain_uuid)>())
|
||||
{
|
||||
}
|
||||
_quick_status_code_from_enum_domain(const _quick_status_code_from_enum_domain &) = default;
|
||||
_quick_status_code_from_enum_domain(_quick_status_code_from_enum_domain &&) = default;
|
||||
_quick_status_code_from_enum_domain &operator=(const _quick_status_code_from_enum_domain &) = default;
|
||||
_quick_status_code_from_enum_domain &operator=(_quick_status_code_from_enum_domain &&) = default;
|
||||
~_quick_status_code_from_enum_domain() = default;
|
||||
|
||||
#if __cplusplus < 201402L && !defined(_MSC_VER)
|
||||
static inline const _quick_status_code_from_enum_domain &get()
|
||||
{
|
||||
static _quick_status_code_from_enum_domain v;
|
||||
return v;
|
||||
}
|
||||
#else
|
||||
static inline constexpr const _quick_status_code_from_enum_domain &get();
|
||||
#endif
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref(_src::domain_name); }
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
// Not sure if a hash table is worth it here, most enumerations won't be long enough to be worth it
|
||||
// Also, until C++ 20's consteval, the hash table would get emitted into the binary, bloating it
|
||||
static BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 const typename _src::mapping *_find_mapping(value_type v) noexcept
|
||||
{
|
||||
for(const auto &i : _src::value_mappings())
|
||||
{
|
||||
if(i.value == v)
|
||||
{
|
||||
return &i;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
// If `errc::success` is in the generic code mapping, it is not a failure
|
||||
const auto *mapping = _find_mapping(static_cast<const quick_status_code_from_enum_code<value_type> &>(code).value());
|
||||
assert(mapping != nullptr);
|
||||
if(mapping != nullptr)
|
||||
{
|
||||
for(errc ec : mapping->code_mappings)
|
||||
{
|
||||
if(ec == errc::success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override
|
||||
{
|
||||
assert(code1.domain() == *this); // NOLINT
|
||||
const auto &c1 = static_cast<const quick_status_code_from_enum_code<value_type> &>(code1); // NOLINT
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const quick_status_code_from_enum_code<value_type> &>(code2); // NOLINT
|
||||
return c1.value() == c2.value();
|
||||
}
|
||||
if(code2.domain() == generic_code_domain)
|
||||
{
|
||||
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
|
||||
const auto *mapping = _find_mapping(c1.value());
|
||||
assert(mapping != nullptr);
|
||||
if(mapping != nullptr)
|
||||
{
|
||||
for(errc ec : mapping->code_mappings)
|
||||
{
|
||||
if(ec == c2.value())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto *mapping = _find_mapping(static_cast<const quick_status_code_from_enum_code<value_type> &>(code).value());
|
||||
assert(mapping != nullptr);
|
||||
if(mapping != nullptr)
|
||||
{
|
||||
if(mapping->code_mappings.size() > 0)
|
||||
{
|
||||
return *mapping->code_mappings.begin();
|
||||
}
|
||||
}
|
||||
return errc::unknown;
|
||||
}
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto *mapping = _find_mapping(static_cast<const quick_status_code_from_enum_code<value_type> &>(code).value());
|
||||
assert(mapping != nullptr);
|
||||
if(mapping != nullptr)
|
||||
{
|
||||
return string_ref(mapping->message);
|
||||
}
|
||||
return string_ref("unknown");
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override
|
||||
{
|
||||
assert(code.domain() == *this); // NOLINT
|
||||
const auto &c = static_cast<const quick_status_code_from_enum_code<value_type> &>(code); // NOLINT
|
||||
throw status_error<_quick_status_code_from_enum_domain>(c);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201402L || defined(_MSC_VER)
|
||||
template <class Enum> constexpr _quick_status_code_from_enum_domain<Enum> quick_status_code_from_enum_domain = {};
|
||||
template <class Enum> inline constexpr const _quick_status_code_from_enum_domain<Enum> &_quick_status_code_from_enum_domain<Enum>::get()
|
||||
{
|
||||
return quick_status_code_from_enum_domain<Enum>;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base, class Enum>
|
||||
struct mixin<Base, _quick_status_code_from_enum_domain<Enum>> : public quick_status_code_from_enum<Enum>::template mixin<Base>
|
||||
{
|
||||
using quick_status_code_from_enum<Enum>::template mixin<Base>::mixin;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,402 @@
|
||||
/* A partial result based on std::variant and proposed std::error
|
||||
(C) 2020-2023 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
|
||||
File Created: Jan 2020
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_RESULT_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_RESULT_HPP
|
||||
|
||||
#include "error.hpp"
|
||||
|
||||
#if __cplusplus >= 201703L || _HAS_CXX17
|
||||
#if __has_include(<variant>)
|
||||
|
||||
#include <exception>
|
||||
#include <variant>
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
template <class T> inline constexpr std::in_place_type_t<T> in_place_type{};
|
||||
|
||||
template <class T> class result;
|
||||
|
||||
//! \brief A trait for detecting result types
|
||||
template <class T> struct is_result : public std::false_type
|
||||
{
|
||||
};
|
||||
template <class T> struct is_result<result<T>> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/*! \brief Exception type representing the failure to retrieve an error.
|
||||
*/
|
||||
class bad_result_access : public std::exception
|
||||
{
|
||||
public:
|
||||
bad_result_access() = default;
|
||||
//! Return an explanatory string
|
||||
virtual const char *what() const noexcept override { return "bad result access"; } // NOLINT
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct void_
|
||||
{
|
||||
};
|
||||
template <class T> using devoid = std::conditional_t<std::is_void_v<T>, void_, T>;
|
||||
} // namespace detail
|
||||
|
||||
/*! \class result
|
||||
\brief A imperfect `result<T>` type with its error type hardcoded to `error`, only available on C++ 17 or later.
|
||||
|
||||
Note that the proper `result<T>` type does not have the possibility of
|
||||
valueless by exception state. This implementation is therefore imperfect.
|
||||
*/
|
||||
template <class T> class result : protected std::variant<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error, detail::devoid<T>>
|
||||
{
|
||||
using _base = std::variant<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error, detail::devoid<T>>;
|
||||
static_assert(!std::is_reference_v<T>, "Type cannot be a reference");
|
||||
static_assert(!std::is_array_v<T>, "Type cannot be an array");
|
||||
static_assert(!std::is_same_v<T, BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error>, "Type cannot be a std::error");
|
||||
// not success nor failure types
|
||||
|
||||
struct _implicit_converting_constructor_tag
|
||||
{
|
||||
};
|
||||
struct _explicit_converting_constructor_tag
|
||||
{
|
||||
};
|
||||
struct _implicit_constructor_tag
|
||||
{
|
||||
};
|
||||
struct _implicit_in_place_value_constructor_tag
|
||||
{
|
||||
};
|
||||
struct _implicit_in_place_error_constructor_tag
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
//! The value type
|
||||
using value_type = T;
|
||||
//! The error type
|
||||
using error_type = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error;
|
||||
//! The value type, if it is available, else a usefully named unusable internal type
|
||||
using value_type_if_enabled = detail::devoid<T>;
|
||||
//! Used to rebind result types
|
||||
template <class U> using rebind = result<U>;
|
||||
|
||||
protected:
|
||||
constexpr void _check() const
|
||||
{
|
||||
if(_base::index() == 0)
|
||||
{
|
||||
std::get_if<0>(this)->throw_exception();
|
||||
}
|
||||
}
|
||||
constexpr
|
||||
#ifdef _MSC_VER
|
||||
__declspec(noreturn)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
__attribute__((noreturn))
|
||||
#endif
|
||||
void _ub()
|
||||
{
|
||||
assert(false); // NOLINT
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
__builtin_unreachable();
|
||||
#elif defined(_MSC_VER)
|
||||
__assume(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr _base &_internal() noexcept { return *this; }
|
||||
constexpr const _base &_internal() const noexcept { return *this; }
|
||||
|
||||
//! Default constructor is disabled
|
||||
result() = delete;
|
||||
//! Copy constructor
|
||||
result(const result &) = delete;
|
||||
//! Move constructor
|
||||
result(result &&) = default;
|
||||
//! Copy assignment
|
||||
result &operator=(const result &) = delete;
|
||||
//! Move assignment
|
||||
result &operator=(result &&) = default;
|
||||
//! Destructor
|
||||
~result() = default;
|
||||
|
||||
//! Implicit result converting move constructor
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>)) constexpr result(result<U> &&o, _implicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
|
||||
: _base(std::move(o))
|
||||
{
|
||||
}
|
||||
//! Implicit result converting copy constructor
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>)) constexpr result(const result<U> &o, _implicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
|
||||
: _base(o)
|
||||
{
|
||||
}
|
||||
//! Explicit result converting move constructor
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>)) constexpr explicit result(result<U> &&o, _explicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
|
||||
: _base(std::move(o))
|
||||
{
|
||||
}
|
||||
//! Explicit result converting copy constructor
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>)) constexpr explicit result(const result<U> &o, _explicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
|
||||
: _base(o)
|
||||
{
|
||||
}
|
||||
|
||||
//! Anything which `std::variant<error, T>` will construct from, we shall implicitly construct from
|
||||
using _base::_base;
|
||||
|
||||
//! Special case `in_place_type_t<void>`
|
||||
constexpr explicit result(std::in_place_type_t<void> /*unused*/) noexcept
|
||||
: _base(in_place_type<detail::void_>)
|
||||
{
|
||||
}
|
||||
|
||||
//! Implicit in-place converting error constructor
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Arg1, class Arg2, class... Args, long = 5) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> && std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
|
||||
&&std::is_constructible_v<error_type, Arg1, Arg2, Args...>))
|
||||
constexpr result(Arg1 &&arg1, Arg2 &&arg2, Args &&...args) noexcept(std::is_nothrow_constructible_v<error_type, Arg1, Arg2, Args...>)
|
||||
: _base(std::in_place_index<0>, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
//! Implicit in-place converting value constructor
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Arg1, class Arg2, class... Args, int = 5) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> && std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
|
||||
&&std::is_constructible_v<value_type, Arg1, Arg2, Args...>))
|
||||
constexpr result(Arg1 &&arg1, Arg2 &&arg2, Args &&...args) noexcept(std::is_nothrow_constructible_v<value_type, Arg1, Arg2, Args...>)
|
||||
: _base(std::in_place_index<1>, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U, class... Args, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<U, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!std::is_same<typename std::decay<U>::type, result>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<U>::type, value_type>::value // not copy/move of value type
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<error_type, MakeStatusCodeResult>::value)) // ADLed status code is compatible
|
||||
constexpr result(U &&v, Args &&...args) noexcept(noexcept(make_status_code(std::declval<U>(), std::declval<Args>()...))) // NOLINT
|
||||
: _base(std::in_place_index<0>, make_status_code(static_cast<U &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
//! Swap with another result
|
||||
constexpr void swap(result &o) noexcept(std::is_nothrow_swappable_v<_base>) { _base::swap(o); }
|
||||
|
||||
//! Clone the result
|
||||
constexpr result clone() const { return has_value() ? result(value()) : result(error().clone()); }
|
||||
|
||||
//! True if result has a value
|
||||
constexpr bool has_value() const noexcept { return _base::index() == 1; }
|
||||
//! True if result has a value
|
||||
explicit operator bool() const noexcept { return has_value(); }
|
||||
//! True if result has an error
|
||||
constexpr bool has_error() const noexcept { return _base::index() == 0; }
|
||||
|
||||
//! Accesses the value if one exists, else calls `.error().throw_exception()`.
|
||||
constexpr value_type_if_enabled &value() &
|
||||
{
|
||||
_check();
|
||||
return std::get<1>(*this);
|
||||
}
|
||||
//! Accesses the value if one exists, else calls `.error().throw_exception()`.
|
||||
constexpr const value_type_if_enabled &value() const &
|
||||
{
|
||||
_check();
|
||||
return std::get<1>(*this);
|
||||
}
|
||||
//! Accesses the value if one exists, else calls `.error().throw_exception()`.
|
||||
constexpr value_type_if_enabled &&value() &&
|
||||
{
|
||||
_check();
|
||||
return std::get<1>(std::move(*this));
|
||||
}
|
||||
//! Accesses the value if one exists, else calls `.error().throw_exception()`.
|
||||
constexpr const value_type_if_enabled &&value() const &&
|
||||
{
|
||||
_check();
|
||||
return std::get<1>(std::move(*this));
|
||||
}
|
||||
|
||||
//! Accesses the error if one exists, else throws `bad_result_access`.
|
||||
constexpr error_type &error() &
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw bad_result_access();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
return *std::get_if<0>(this);
|
||||
}
|
||||
//! Accesses the error if one exists, else throws `bad_result_access`.
|
||||
constexpr const error_type &error() const &
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw bad_result_access();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
return *std::get_if<0>(this);
|
||||
}
|
||||
//! Accesses the error if one exists, else throws `bad_result_access`.
|
||||
constexpr error_type &&error() &&
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw bad_result_access();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
return std::move(*std::get_if<0>(this));
|
||||
}
|
||||
//! Accesses the error if one exists, else throws `bad_result_access`.
|
||||
constexpr const error_type &&error() const &&
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw bad_result_access();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
return std::move(*std::get_if<0>(this));
|
||||
}
|
||||
|
||||
//! Accesses the value, being UB if none exists
|
||||
constexpr value_type_if_enabled &assume_value() &noexcept
|
||||
{
|
||||
if(!has_value())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return *std::get_if<1>(this);
|
||||
}
|
||||
//! Accesses the error, being UB if none exists
|
||||
constexpr const value_type_if_enabled &assume_value() const &noexcept
|
||||
{
|
||||
if(!has_value())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return *std::get_if<1>(this);
|
||||
}
|
||||
//! Accesses the error, being UB if none exists
|
||||
constexpr value_type_if_enabled &&assume_value() &&noexcept
|
||||
{
|
||||
if(!has_value())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return std::move(*std::get_if<1>(this));
|
||||
}
|
||||
//! Accesses the error, being UB if none exists
|
||||
constexpr const value_type_if_enabled &&assume_value() const &&noexcept
|
||||
{
|
||||
if(!has_value())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return std::move(*std::get_if<1>(this));
|
||||
}
|
||||
|
||||
//! Accesses the error, being UB if none exists
|
||||
constexpr error_type &assume_error() &noexcept
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return *std::get_if<0>(this);
|
||||
}
|
||||
//! Accesses the error, being UB if none exists
|
||||
constexpr const error_type &assume_error() const &noexcept
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return *std::get_if<0>(this);
|
||||
}
|
||||
//! Accesses the error, being UB if none exists
|
||||
constexpr error_type &&assume_error() &&noexcept
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return std::move(*std::get_if<0>(this));
|
||||
}
|
||||
//! Accesses the error, being UB if none exists
|
||||
constexpr const error_type &&assume_error() const &&noexcept
|
||||
{
|
||||
if(!has_error())
|
||||
{
|
||||
_ub();
|
||||
}
|
||||
return std::move(*std::get_if<0>(this));
|
||||
}
|
||||
};
|
||||
|
||||
//! True if the two results compare equal.
|
||||
template <class T, class U, typename = decltype(std::declval<T>() == std::declval<U>())> constexpr inline bool operator==(const result<T> &a, const result<U> &b) noexcept
|
||||
{
|
||||
const auto &x = a._internal();
|
||||
return x == b;
|
||||
}
|
||||
//! True if the two results compare unequal.
|
||||
template <class T, class U, typename = decltype(std::declval<T>() != std::declval<U>())> constexpr inline bool operator!=(const result<T> &a, const result<U> &b) noexcept
|
||||
{
|
||||
const auto &x = a._internal();
|
||||
return x != b;
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,718 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018 - 2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_CODE_HPP
|
||||
|
||||
#include "status_code_domain.hpp"
|
||||
|
||||
#if(__cplusplus >= 201700 || _HAS_CXX17) && !defined(BOOST_OUTCOME_SYSTEM_ERROR2_DISABLE_STD_IN_PLACE)
|
||||
// 0.26
|
||||
#include <utility> // for in_place
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
using in_place_t = std::in_place_t;
|
||||
using std::in_place;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#else
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
//! Aliases `std::in_place_t` if on C++ 17 or later, else defined locally.
|
||||
struct in_place_t
|
||||
{
|
||||
explicit in_place_t() = default;
|
||||
};
|
||||
//! Aliases `std::in_place` if on C++ 17 or later, else defined locally.
|
||||
constexpr in_place_t in_place{};
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
//! Namespace for user injected mixins
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base, class T> struct mixin : public Base
|
||||
{
|
||||
using Base::Base;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
namespace detail
|
||||
{
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class ErasedType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(traits::is_move_bitcopying<ErasedType>::value))
|
||||
struct erased
|
||||
{
|
||||
using value_type = ErasedType;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/*! The tag type used to specialise erased editions of `status_code<D>`.
|
||||
Available only if `ErasedType` satisfies `traits::is_move_bitcopying<ErasedType>::value`.
|
||||
*/
|
||||
template <class ErasedType> //
|
||||
using status_code_erased_tag_type = detail::erased<ErasedType>;
|
||||
|
||||
/*! Specialise this template to quickly wrap a third party enumeration into a
|
||||
custom status code domain.
|
||||
|
||||
Use like this:
|
||||
|
||||
```c++
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
template <> struct quick_status_code_from_enum<AnotherCode> : quick_status_code_from_enum_defaults<AnotherCode>
|
||||
{
|
||||
// Text name of the enum
|
||||
static constexpr const auto domain_name = "Another Code";
|
||||
// Unique UUID for the enum. PLEASE use https://www.random.org/cgi-bin/randbyte?nbytes=16&format=h
|
||||
static constexpr const auto domain_uuid = "{be201f65-3962-dd0e-1266-a72e63776a42}";
|
||||
// Map of each enum value to its text string, and list of semantically equivalent errc's
|
||||
static const std::initializer_list<mapping> &value_mappings()
|
||||
{
|
||||
static const std::initializer_list<mapping<AnotherCode>> v = {
|
||||
// Format is: { enum value, "string representation", { list of errc mappings ... } }
|
||||
{AnotherCode::success1, "Success 1", {errc::success}}, //
|
||||
{AnotherCode::goaway, "Go away", {errc::permission_denied}}, //
|
||||
{AnotherCode::success2, "Success 2", {errc::success}}, //
|
||||
{AnotherCode::error2, "Error 2", {}}, //
|
||||
};
|
||||
return v;
|
||||
}
|
||||
// Completely optional definition of mixin for the status code synthesised from `Enum`. It can be omitted.
|
||||
template <class Base> struct mixin : Base
|
||||
{
|
||||
using Base::Base;
|
||||
constexpr int custom_method() const { return 42; }
|
||||
};
|
||||
};
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
```
|
||||
|
||||
Note that if the `errc` mapping contains `errc::success`, then
|
||||
the enumeration value is considered to be a successful value.
|
||||
Otherwise it is considered to be a failure value.
|
||||
|
||||
The first value in the `errc` mapping is the one chosen as the
|
||||
`generic_code` conversion. Other values are used during equivalence
|
||||
comparisons.
|
||||
*/
|
||||
template <class Enum> struct quick_status_code_from_enum;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T> struct is_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_status_code<status_code<T>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <class T> struct is_erased_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_erased_status_code<status_code<detail::erased<T>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 8
|
||||
// From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4436.pdf
|
||||
namespace impl
|
||||
{
|
||||
template <typename... Ts> struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
|
||||
template <class...> struct types
|
||||
{
|
||||
using type = types;
|
||||
};
|
||||
template <template <class...> class T, class types, class = void> struct test_apply
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <template <class...> class T, class... Ts> struct test_apply<T, types<Ts...>, void_t<T<Ts...>>>
|
||||
{
|
||||
using type = T<Ts...>;
|
||||
};
|
||||
} // namespace impl
|
||||
template <template <class...> class T, class... Ts> using test_apply = impl::test_apply<T, impl::types<Ts...>>;
|
||||
|
||||
template <class T, class... Args> using get_make_status_code_result = decltype(make_status_code(std::declval<T>(), std::declval<Args>()...));
|
||||
template <class... Args> using safe_get_make_status_code_result = test_apply<get_make_status_code_result, Args...>;
|
||||
|
||||
#else
|
||||
|
||||
// ICE avoidance form for GCCs before 8. Note this form doesn't prevent recursive make_status_code ADL instantation,
|
||||
// so in certain corner cases this will break. On the other hand, more useful than an ICE.
|
||||
namespace impl
|
||||
{
|
||||
template <typename... Ts> struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
|
||||
template <class...> struct types
|
||||
{
|
||||
using type = types;
|
||||
};
|
||||
template <typename Types, typename = void> struct make_status_code_rettype
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename... Args> using get_make_status_code_result = decltype(make_status_code(std::declval<Args>()...));
|
||||
template <typename... Args> struct make_status_code_rettype<types<Args...>, void_t<get_make_status_code_result<Args...>>>
|
||||
{
|
||||
using type = get_make_status_code_result<Args...>;
|
||||
};
|
||||
} // namespace impl
|
||||
template <class... Args> struct safe_get_make_status_code_result
|
||||
{
|
||||
using type = typename impl::make_status_code_rettype<impl::types<Args...>>::type;
|
||||
};
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
//! Trait returning true if the type is a status code.
|
||||
template <class T> struct is_status_code
|
||||
{
|
||||
static constexpr bool value =
|
||||
detail::is_status_code<typename std::decay<T>::type>::value || detail::is_erased_status_code<typename std::decay<T>::type>::value;
|
||||
};
|
||||
|
||||
/*! A type erased lightweight status code reflecting empty, success, or failure.
|
||||
Differs from `status_code<erased<>>` by being always available irrespective of
|
||||
the domain's value type, but cannot be copied, moved, nor destructed. Thus one
|
||||
always passes this around by const lvalue reference.
|
||||
*/
|
||||
template <> class BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI status_code<void>
|
||||
{
|
||||
template <class T> friend class status_code;
|
||||
|
||||
public:
|
||||
//! The type of the domain.
|
||||
using domain_type = void;
|
||||
//! The type of the status code.
|
||||
using value_type = void;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename status_code_domain::string_ref;
|
||||
|
||||
protected:
|
||||
const status_code_domain *_domain{nullptr};
|
||||
|
||||
protected:
|
||||
//! No default construction at type erased level
|
||||
status_code() = default;
|
||||
//! No public copying at type erased level
|
||||
status_code(const status_code &) = default;
|
||||
//! No public moving at type erased level
|
||||
status_code(status_code &&) = default;
|
||||
//! No public assignment at type erased level
|
||||
status_code &operator=(const status_code &) = default;
|
||||
//! No public assignment at type erased level
|
||||
status_code &operator=(status_code &&) = default;
|
||||
//! No public destruction at type erased level
|
||||
~status_code() = default;
|
||||
|
||||
//! Used to construct a non-empty type erased status code
|
||||
constexpr explicit status_code(const status_code_domain *v) noexcept
|
||||
: _domain(v)
|
||||
{
|
||||
}
|
||||
|
||||
// Used to work around triggering a ubsan failure. Do NOT remove!
|
||||
constexpr const status_code_domain *_domain_ptr() const noexcept { return _domain; }
|
||||
|
||||
public:
|
||||
//! Return the status code domain.
|
||||
constexpr const status_code_domain &domain() const noexcept { return *_domain; }
|
||||
//! True if the status code is empty.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD constexpr bool empty() const noexcept { return _domain == nullptr; }
|
||||
|
||||
//! Return a reference to a string textually representing a code.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 string_ref message() const noexcept
|
||||
{
|
||||
// Avoid MSVC's buggy ternary operator for expensive to destruct things
|
||||
if(_domain != nullptr)
|
||||
{
|
||||
return _domain->_do_message(*this);
|
||||
}
|
||||
return string_ref("(empty)");
|
||||
}
|
||||
//! True if code means success.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 bool success() const noexcept { return (_domain != nullptr) ? !_domain->_do_failure(*this) : false; }
|
||||
//! True if code means failure.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 bool failure() const noexcept { return (_domain != nullptr) ? _domain->_do_failure(*this) : false; }
|
||||
/*! True if code is strictly (and potentially non-transitively) semantically equivalent to another code in another domain.
|
||||
Note that usually non-semantic i.e. pure value comparison is used when the other status code has the same domain.
|
||||
As `equivalent()` will try mapping to generic code, this usually captures when two codes have the same semantic
|
||||
meaning in `equivalent()`.
|
||||
*/
|
||||
template <class T> BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 bool strictly_equivalent(const status_code<T> &o) const noexcept
|
||||
{
|
||||
if(_domain && o._domain)
|
||||
{
|
||||
return _domain->_do_equivalent(*this, o);
|
||||
}
|
||||
// If we are both empty, we are equivalent
|
||||
if(!_domain && !o._domain)
|
||||
{
|
||||
return true; // NOLINT
|
||||
}
|
||||
// Otherwise not equivalent
|
||||
return false;
|
||||
}
|
||||
/*! True if code is equivalent, by any means, to another code in another domain (guaranteed transitive).
|
||||
Firstly `strictly_equivalent()` is run in both directions. If neither succeeds, each domain is asked
|
||||
for the equivalent generic code and those are compared.
|
||||
*/
|
||||
template <class T> BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool equivalent(const status_code<T> &o) const noexcept;
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
//! Throw a code as a C++ exception.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN void throw_exception() const
|
||||
{
|
||||
_domain->_do_throw_exception(*this);
|
||||
abort(); // suppress buggy GCC warning
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class DomainType> struct get_domain_value_type
|
||||
{
|
||||
using domain_type = DomainType;
|
||||
using value_type = typename domain_type::value_type;
|
||||
};
|
||||
template <class ErasedType> struct get_domain_value_type<erased<ErasedType>>
|
||||
{
|
||||
using domain_type = status_code_domain;
|
||||
using value_type = ErasedType;
|
||||
};
|
||||
template <class DomainType> class BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI status_code_storage : public status_code<void>
|
||||
{
|
||||
static_assert(!std::is_void<DomainType>::value, "status_code_storage<void> should never occur!");
|
||||
using _base = status_code<void>;
|
||||
|
||||
public:
|
||||
//! The type of the domain.
|
||||
using domain_type = typename get_domain_value_type<DomainType>::domain_type;
|
||||
//! The type of the status code.
|
||||
using value_type = typename get_domain_value_type<DomainType>::value_type;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename domain_type::string_ref;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static_assert(std::is_move_constructible<value_type>::value || std::is_copy_constructible<value_type>::value,
|
||||
"DomainType::value_type is neither move nor copy constructible!");
|
||||
static_assert(!std::is_default_constructible<value_type>::value || std::is_nothrow_default_constructible<value_type>::value,
|
||||
"DomainType::value_type is not nothrow default constructible!");
|
||||
static_assert(!std::is_move_constructible<value_type>::value || std::is_nothrow_move_constructible<value_type>::value,
|
||||
"DomainType::value_type is not nothrow move constructible!");
|
||||
static_assert(std::is_nothrow_destructible<value_type>::value, "DomainType::value_type is not nothrow destructible!");
|
||||
#endif
|
||||
|
||||
// Replace the type erased implementations with type aware implementations for better codegen
|
||||
//! Return the status code domain.
|
||||
constexpr const domain_type &domain() const noexcept { return *static_cast<const domain_type *>(this->_domain); }
|
||||
|
||||
//! Reset the code to empty.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 void clear() noexcept
|
||||
{
|
||||
this->_value.~value_type();
|
||||
this->_domain = nullptr;
|
||||
new(std::addressof(this->_value)) value_type();
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr value_type &value() & noexcept { return this->_value; }
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr value_type &&value() && noexcept { return static_cast<value_type &&>(this->_value); }
|
||||
#endif
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr const value_type &value() const & noexcept { return this->_value; }
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr const value_type &&value() const && noexcept { return static_cast<const value_type &&>(this->_value); }
|
||||
|
||||
protected:
|
||||
status_code_storage() = default;
|
||||
status_code_storage(const status_code_storage &) = default;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code_storage(status_code_storage &&o) noexcept
|
||||
: _base(static_cast<status_code_storage &&>(o))
|
||||
, _value(static_cast<status_code_storage &&>(o)._value)
|
||||
{
|
||||
o._domain = nullptr;
|
||||
}
|
||||
status_code_storage &operator=(const status_code_storage &) = default;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code_storage &operator=(status_code_storage &&o) noexcept
|
||||
{
|
||||
this->~status_code_storage();
|
||||
new(this) status_code_storage(static_cast<status_code_storage &&>(o));
|
||||
return *this;
|
||||
}
|
||||
~status_code_storage() = default;
|
||||
|
||||
value_type _value{};
|
||||
struct _value_type_constructor
|
||||
{
|
||||
};
|
||||
template <class... Args>
|
||||
constexpr status_code_storage(_value_type_constructor /*unused*/, const status_code_domain *v, Args &&...args)
|
||||
: _base(v)
|
||||
, _value(static_cast<Args &&>(args)...)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class DomainType> struct has_stateful_mixin
|
||||
{
|
||||
static constexpr bool value = (sizeof(status_code_storage<DomainType>) != sizeof(mixins::mixin<status_code_storage<DomainType>, DomainType>));
|
||||
};
|
||||
|
||||
template <class ToDomain, class FromDomain> struct domain_value_type_erasure_is_safe
|
||||
{
|
||||
using to_value_type = typename get_domain_value_type<ToDomain>::value_type;
|
||||
using from_value_type = typename get_domain_value_type<FromDomain>::value_type;
|
||||
static constexpr bool value = traits::is_move_bitcopying<to_value_type>::value //
|
||||
&& traits::is_move_bitcopying<from_value_type>::value //
|
||||
&& sizeof(status_code_storage<FromDomain>) <= sizeof(status_code_storage<ToDomain>) //
|
||||
&& !has_stateful_mixin<FromDomain>::value;
|
||||
};
|
||||
template <class ToDomain> struct domain_value_type_erasure_is_safe<ToDomain, void>
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
namespace traits
|
||||
{
|
||||
//! Determines whether the mixin contained in `StatusCode` contains non-static member variables.
|
||||
template <class StatusCode> using has_stateful_mixin = detail::has_stateful_mixin<typename detail::remove_cvref<StatusCode>::type::value_type>;
|
||||
|
||||
//! Determines whether the status code `From` can be type erased into the status code `To`.
|
||||
template <class To, class From>
|
||||
using is_type_erasable_to =
|
||||
detail::domain_value_type_erasure_is_safe<typename detail::remove_cvref<To>::type::domain_type, typename detail::remove_cvref<From>::type::domain_type>;
|
||||
} // namespace traits
|
||||
|
||||
/*! A lightweight, typed, status code reflecting empty, success, or failure.
|
||||
This is the main workhorse of the system_error2 library. Its characteristics reflect the value type
|
||||
set by its domain type, so if that value type is move-only or trivial, so is this.
|
||||
|
||||
An ADL discovered helper function `make_status_code(T, Args...)` is looked up by one of the constructors.
|
||||
If it is found, and it generates a status code compatible with this status code, implicit construction
|
||||
is made available.
|
||||
|
||||
You may mix in custom member functions and member function overrides by injecting a specialisation of
|
||||
`mixins::mixin<Base, YourDomainType>`. Your mixin must inherit from `Base`. Your mixin can carry state,
|
||||
but if it does, it will no longer be possible to construct erased status codes from such unerased status
|
||||
codes.
|
||||
*/
|
||||
template <class DomainType> class BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI status_code : public mixins::mixin<detail::status_code_storage<DomainType>, DomainType>
|
||||
{
|
||||
template <class T> friend class status_code;
|
||||
using _base = mixins::mixin<detail::status_code_storage<DomainType>, DomainType>;
|
||||
|
||||
public:
|
||||
//! The type of the domain.
|
||||
using domain_type = DomainType;
|
||||
//! The type of the status code.
|
||||
using value_type = typename domain_type::value_type;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename domain_type::string_ref;
|
||||
|
||||
protected:
|
||||
using _base::_base;
|
||||
|
||||
public:
|
||||
//! Default construction to empty
|
||||
status_code() = default;
|
||||
//! Copy constructor
|
||||
status_code(const status_code &) = default;
|
||||
//! Move constructor
|
||||
status_code(status_code &&) = default; // NOLINT
|
||||
//! Copy assignment
|
||||
status_code &operator=(const status_code &) = default;
|
||||
//! Move assignment
|
||||
status_code &operator=(status_code &&) = default; // NOLINT
|
||||
~status_code() = default;
|
||||
|
||||
//! Return a copy of the code.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code clone() const { return *this; }
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH ERRORED_STATUS_CODE *****/
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(
|
||||
class T, class... Args, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<T, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!std::is_same<typename std::decay<T>::type, status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, in_place_t>::value // not in_place_t
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<status_code, MakeStatusCodeResult>::value)) // ADLed status code is compatible
|
||||
constexpr status_code(T &&v, Args &&...args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
}
|
||||
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Enum, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type) // Enumeration has been activated
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible<status_code, QuickStatusCodeType>::value)) // Its status code is compatible
|
||||
constexpr status_code(Enum &&v) noexcept(std::is_nothrow_constructible<status_code, QuickStatusCodeType>::value) // NOLINT
|
||||
: status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
|
||||
{
|
||||
}
|
||||
//! Explicit in-place construction. Disables if `domain_type::get()` is not a valid expression.
|
||||
template <class... Args>
|
||||
constexpr explicit status_code(in_place_t /*unused */, Args &&...args) noexcept(std::is_nothrow_constructible<value_type, Args &&...>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), static_cast<Args &&>(args)...)
|
||||
{
|
||||
}
|
||||
//! Explicit in-place construction from initialiser list. Disables if `domain_type::get()` is not a valid expression.
|
||||
template <class T, class... Args>
|
||||
constexpr explicit status_code(in_place_t /*unused */, std::initializer_list<T> il,
|
||||
Args &&...args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<T>, Args &&...>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), il, static_cast<Args &&>(args)...)
|
||||
{
|
||||
}
|
||||
//! Explicit copy construction from a `value_type`. Disables if `domain_type::get()` is not a valid expression.
|
||||
constexpr explicit status_code(const value_type &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), v)
|
||||
{
|
||||
}
|
||||
//! Explicit move construction from a `value_type`. Disables if `domain_type::get()` is not a valid expression.
|
||||
constexpr explicit status_code(value_type &&v) noexcept(std::is_nothrow_move_constructible<value_type>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), static_cast<value_type &&>(v))
|
||||
{
|
||||
}
|
||||
/*! Explicit construction from an erased status code. Available only if
|
||||
`value_type` is trivially copyable or move bitcopying, and `sizeof(status_code) <= sizeof(status_code<erased<>>)`.
|
||||
Does not check if domains are equal.
|
||||
*/
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class ErasedType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<domain_type, detail::erased<ErasedType>>::value))
|
||||
constexpr explicit status_code(const status_code<detail::erased<ErasedType>> &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: status_code(detail::erasure_cast<value_type>(v.value()))
|
||||
{
|
||||
#if __cplusplus >= 201400
|
||||
assert(v.domain() == this->domain());
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Return a reference to a string textually representing a code.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 string_ref message() const noexcept
|
||||
{
|
||||
// Avoid MSVC's buggy ternary operator for expensive to destruct things
|
||||
if(this->_domain != nullptr)
|
||||
{
|
||||
return string_ref(this->domain()._do_message(*this));
|
||||
}
|
||||
return string_ref("(empty)");
|
||||
}
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class DomainType> struct is_move_bitcopying<status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = is_move_bitcopying<typename DomainType::value_type>::value;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
|
||||
/*! Type erased, move-only status_code, unlike `status_code<void>` which cannot be moved nor destroyed. Available
|
||||
only if `erased<>` is available, which is when the domain's type is trivially
|
||||
copyable or is move relocatable, and if the size of the domain's typed error code is less than or equal to
|
||||
this erased error code. Copy construction is disabled, but if you want a copy call `.clone()`.
|
||||
|
||||
An ADL discovered helper function `make_status_code(T, Args...)` is looked up by one of the constructors.
|
||||
If it is found, and it generates a status code compatible with this status code, implicit construction
|
||||
is made available.
|
||||
*/
|
||||
template <class ErasedType>
|
||||
class BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI status_code<detail::erased<ErasedType>>
|
||||
: public mixins::mixin<detail::status_code_storage<detail::erased<ErasedType>>, detail::erased<ErasedType>>
|
||||
{
|
||||
template <class T> friend class status_code;
|
||||
using _base = mixins::mixin<detail::status_code_storage<detail::erased<ErasedType>>, detail::erased<ErasedType>>;
|
||||
|
||||
public:
|
||||
//! The type of the domain (void, as it is erased).
|
||||
using domain_type = void;
|
||||
//! The type of the erased status code.
|
||||
using value_type = ErasedType;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename _base::string_ref;
|
||||
|
||||
public:
|
||||
//! Default construction to empty
|
||||
status_code() = default;
|
||||
//! Copy constructor
|
||||
status_code(const status_code &) = delete;
|
||||
//! Move constructor
|
||||
status_code(status_code &&) = default; // NOLINT
|
||||
//! Copy assignment
|
||||
status_code &operator=(const status_code &) = delete;
|
||||
//! Move assignment
|
||||
status_code &operator=(status_code &&) = default; // NOLINT
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 ~status_code()
|
||||
{
|
||||
if(nullptr != this->_domain)
|
||||
{
|
||||
status_code_domain::payload_info_t info{sizeof(value_type), sizeof(status_code), alignof(status_code)};
|
||||
this->_domain->_do_erased_destroy(*this, info);
|
||||
}
|
||||
}
|
||||
|
||||
//! Return a copy of the erased code by asking the domain to perform the erased copy.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 status_code clone() const
|
||||
{
|
||||
if(nullptr == this->_domain)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
status_code x;
|
||||
if(!this->_domain->_do_erased_copy(x, *this, this->_domain->payload_info()))
|
||||
{
|
||||
abort(); // should not be possible
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH ERRORED_STATUS_CODE *****/
|
||||
//! Implicit copy construction from any other status code if its value type is trivially copyable, it would fit into our storage, and it is not an erased
|
||||
//! status code.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<detail::erased<ErasedType>, DomainType>::value),
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!detail::is_erased_status_code<status_code<typename std::decay<DomainType>::type>>::value))
|
||||
constexpr status_code(const status_code<DomainType> &v) noexcept // NOLINT
|
||||
: _base(typename _base::_value_type_constructor{}, v._domain_ptr(), detail::erasure_cast<value_type>(v.value()))
|
||||
{
|
||||
}
|
||||
//! Implicit move construction from any other status code if its value type is trivially copyable or move bitcopying and it would fit into our storage
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType) //
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(detail::domain_value_type_erasure_is_safe<detail::erased<ErasedType>, DomainType>::value))
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code(status_code<DomainType> &&v) noexcept // NOLINT
|
||||
: _base(typename _base::_value_type_constructor{}, v._domain_ptr(), detail::erasure_cast<value_type>(v.value()))
|
||||
{
|
||||
alignas(alignof(typename DomainType::value_type)) char buffer[sizeof(typename DomainType::value_type)];
|
||||
new(buffer) typename DomainType::value_type(static_cast<status_code<DomainType> &&>(v).value());
|
||||
// deliberately do not destruct value moved into buffer
|
||||
(void) buffer;
|
||||
v._domain = nullptr;
|
||||
}
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(
|
||||
class T, class... Args, //
|
||||
class MakeStatusCodeResult =
|
||||
typename detail::safe_get_make_status_code_result<T, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!std::is_same<typename std::decay<T>::type, status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, value_type>::value // not copy/move of value type
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<status_code, MakeStatusCodeResult>::value)) // ADLed status code is compatible
|
||||
constexpr status_code(T &&v, Args &&...args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Enum, //
|
||||
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type) // Enumeration has been activated
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible<status_code, QuickStatusCodeType>::value)) // Its status code is compatible
|
||||
constexpr status_code(Enum &&v) noexcept(std::is_nothrow_constructible<status_code, QuickStatusCodeType>::value) // NOLINT
|
||||
: status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
//! Explicit copy construction from an unknown status code. Note that this will throw an exception if its value type is not trivially copyable or would not
|
||||
//! fit into our storage or the source domain's `_do_erased_copy()` refused the copy.
|
||||
explicit BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code(const status_code<void> &v) // NOLINT
|
||||
: _base(typename _base::_value_type_constructor{}, v._domain_ptr(), value_type{})
|
||||
{
|
||||
status_code_domain::payload_info_t info{sizeof(value_type), sizeof(status_code), alignof(status_code)};
|
||||
if(this->_domain->_do_erased_copy(*this, v, info))
|
||||
{
|
||||
return;
|
||||
}
|
||||
struct _ final : public std::exception
|
||||
{
|
||||
virtual const char *what() const noexcept override { return "status_code: source domain's erased copy function returned failure or refusal"; }
|
||||
};
|
||||
throw _{};
|
||||
}
|
||||
#endif
|
||||
//! Tagged copy construction from an unknown status code. Note that this will be empty if its value type is not trivially copyable or would not fit into our
|
||||
//! storage or the source domain's `_do_erased_copy()` refused the copy.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 status_code(std::nothrow_t, const status_code<void> &v) noexcept // NOLINT
|
||||
: _base(typename _base::_value_type_constructor{}, v._domain_ptr(), value_type{})
|
||||
{
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
try
|
||||
#endif
|
||||
{
|
||||
status_code_domain::payload_info_t info{sizeof(value_type), sizeof(status_code), alignof(status_code)};
|
||||
if(this->_domain->_do_erased_copy(*this, v, info))
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->_domain = nullptr;
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
catch(...)
|
||||
{
|
||||
this->_domain = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**** By rights ought to be removed in any formal standard ****/
|
||||
//! Reset the code to empty.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 void clear() noexcept { *this = status_code(); }
|
||||
//! Return the erased `value_type` by value.
|
||||
constexpr value_type value() const noexcept { return this->_value; }
|
||||
};
|
||||
|
||||
/*! An erased type specialisation of `status_code<D>`.
|
||||
Available only if `ErasedType` satisfies `traits::is_move_bitcopying<ErasedType>::value`.
|
||||
*/
|
||||
template <class ErasedType> using erased_status_code = status_code<detail::erased<ErasedType>>;
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class ErasedType> struct is_move_bitcopying<status_code<detail::erased<ErasedType>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
/*! The main workhorse of the system_error2 library, can be typed (`status_code<DomainType>`), erased-immutable (`status_code<void>`) or erased-mutable (`status_code<erased<T>>`).
|
||||
/*! The main workhorse of the system_error2 library, can be typed (`status_code<DomainType>`), erased-immutable (`status_code<void>`) or erased-mutable
|
||||
(`status_code<erased<T>>`).
|
||||
|
||||
Be careful of placing these into containers! Equality and inequality operators are
|
||||
*semantic* not exact. Therefore two distinct items will test true! To help prevent
|
||||
@@ -52,17 +53,56 @@ using generic_code = status_code<_generic_code_domain>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class StatusCode> class indirecting_domain;
|
||||
template <class T> struct status_code_sizer
|
||||
template <class StatusCode, class Allocator> class indirecting_domain;
|
||||
/* We are severely limited by needing to retain C++ 11 compatibility when doing
|
||||
constexpr string parsing. MSVC lets you throw exceptions within a constexpr
|
||||
evaluation context when exceptions are globally disabled, but won't let you
|
||||
divide by zero, even if never evaluated, ever in constexpr. GCC and clang won't
|
||||
let you throw exceptions, ever, if exceptions are globally disabled. So let's
|
||||
use the trick of divide by zero in constexpr on GCC and clang if and only if
|
||||
exceptions are globally disabled.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdiv-by-zero"
|
||||
#endif
|
||||
#if defined(__cpp_exceptions) || (defined(_MSC_VER) && !defined(__clang__))
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_FAIL_CONSTEXPR(msg) throw msg
|
||||
#else
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_FAIL_CONSTEXPR(msg) ((void) msg, 1 / 0)
|
||||
#endif
|
||||
constexpr inline unsigned long long parse_hex_byte(char c)
|
||||
{
|
||||
void *a;
|
||||
T b;
|
||||
};
|
||||
template <class To, class From> struct type_erasure_is_safe
|
||||
return ('0' <= c && c <= '9') ? (c - '0') :
|
||||
('a' <= c && c <= 'f') ? (10 + c - 'a') :
|
||||
('A' <= c && c <= 'F') ? (10 + c - 'A') :
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_FAIL_CONSTEXPR("Invalid character in UUID");
|
||||
}
|
||||
constexpr inline unsigned long long parse_uuid2(const char *s)
|
||||
{
|
||||
static constexpr bool value = traits::is_move_relocating<From>::value //
|
||||
&& (sizeof(status_code_sizer<From>) <= sizeof(status_code_sizer<To>));
|
||||
};
|
||||
return ((parse_hex_byte(s[0]) << 0) | (parse_hex_byte(s[1]) << 4) | (parse_hex_byte(s[2]) << 8) | (parse_hex_byte(s[3]) << 12) |
|
||||
(parse_hex_byte(s[4]) << 16) | (parse_hex_byte(s[5]) << 20) | (parse_hex_byte(s[6]) << 24) | (parse_hex_byte(s[7]) << 28) |
|
||||
(parse_hex_byte(s[9]) << 32) | (parse_hex_byte(s[10]) << 36) | (parse_hex_byte(s[11]) << 40) | (parse_hex_byte(s[12]) << 44) |
|
||||
(parse_hex_byte(s[14]) << 48) | (parse_hex_byte(s[15]) << 52) | (parse_hex_byte(s[16]) << 56) | (parse_hex_byte(s[17]) << 60)) //
|
||||
^ //
|
||||
((parse_hex_byte(s[19]) << 0) | (parse_hex_byte(s[20]) << 4) | (parse_hex_byte(s[21]) << 8) | (parse_hex_byte(s[22]) << 12) |
|
||||
(parse_hex_byte(s[24]) << 16) | (parse_hex_byte(s[25]) << 20) | (parse_hex_byte(s[26]) << 24) | (parse_hex_byte(s[27]) << 28) |
|
||||
(parse_hex_byte(s[28]) << 32) | (parse_hex_byte(s[29]) << 36) | (parse_hex_byte(s[30]) << 40) | (parse_hex_byte(s[31]) << 44) |
|
||||
(parse_hex_byte(s[32]) << 48) | (parse_hex_byte(s[33]) << 52) | (parse_hex_byte(s[34]) << 56) | (parse_hex_byte(s[35]) << 60));
|
||||
}
|
||||
template <size_t N> constexpr inline unsigned long long parse_uuid_from_array(const char (&uuid)[N])
|
||||
{
|
||||
return (N == 37) ? parse_uuid2(uuid) : ((N == 39) ? parse_uuid2(uuid + 1) : BOOST_OUTCOME_SYSTEM_ERROR2_FAIL_CONSTEXPR("UUID does not have correct length"));
|
||||
}
|
||||
template <size_t N> constexpr inline unsigned long long parse_uuid_from_pointer(const char *uuid)
|
||||
{
|
||||
return (N == 36) ? parse_uuid2(uuid) : ((N == 38) ? parse_uuid2(uuid + 1) : BOOST_OUTCOME_SYSTEM_ERROR2_FAIL_CONSTEXPR("UUID does not have correct length"));
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
static constexpr unsigned long long test_uuid_parse = parse_uuid_from_array("430f1201-94fc-06c7-430f-120194fc06c7");
|
||||
// static constexpr unsigned long long test_uuid_parse2 = parse_uuid_from_array("x30f1201-94fc-06c7-430f-120194fc06c7");
|
||||
} // namespace detail
|
||||
|
||||
/*! Abstract base class for a coding domain of a status code.
|
||||
@@ -70,7 +110,7 @@ namespace detail
|
||||
class status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode> friend class indirecting_domain;
|
||||
template <class StatusCode, class Allocator> friend class indirecting_domain;
|
||||
|
||||
public:
|
||||
//! Type of the unique id for this domain.
|
||||
@@ -116,7 +156,7 @@ public:
|
||||
{
|
||||
(void) dest;
|
||||
(void) src;
|
||||
assert(dest->_thunk == _checking_string_thunk); // NOLINT
|
||||
assert(dest->_thunk == _checking_string_thunk); // NOLINT
|
||||
assert(src == nullptr || src->_thunk == _checking_string_thunk); // NOLINT
|
||||
// do nothing
|
||||
}
|
||||
@@ -130,24 +170,30 @@ public:
|
||||
//! Handler for when operations occur
|
||||
const _thunk_spec _thunk{nullptr};
|
||||
|
||||
constexpr explicit string_ref(_thunk_spec thunk) noexcept : _thunk(thunk) {}
|
||||
constexpr explicit string_ref(_thunk_spec thunk) noexcept
|
||||
: _thunk(thunk)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
//! Construct from a C string literal
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 explicit string_ref(const char *str, size_type len = static_cast<size_type>(-1), void *state0 = nullptr, void *state1 = nullptr, void *state2 = nullptr,
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 explicit string_ref(const char *str, size_type len = static_cast<size_type>(-1), void *state0 = nullptr, void *state1 = nullptr,
|
||||
void *state2 = nullptr,
|
||||
#ifndef NDEBUG
|
||||
_thunk_spec thunk = _checking_string_thunk
|
||||
#else
|
||||
_thunk_spec thunk = nullptr
|
||||
#endif
|
||||
) noexcept : _begin(str),
|
||||
_end((len == static_cast<size_type>(-1)) ? (str + detail::cstrlen(str)) : (str + len)), // NOLINT
|
||||
_state{state0, state1, state2},
|
||||
_thunk(thunk)
|
||||
) noexcept
|
||||
: _begin(str)
|
||||
, _end((len == static_cast<size_type>(-1)) ? (str + detail::cstrlen(str)) : (str + len))
|
||||
, // NOLINT
|
||||
_state{state0, state1, state2}
|
||||
, _thunk(thunk)
|
||||
{
|
||||
}
|
||||
//! Copy construct the derived implementation.
|
||||
string_ref(const string_ref &o)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 string_ref(const string_ref &o)
|
||||
: _begin(o._begin)
|
||||
, _end(o._end)
|
||||
, _state{o._state[0], o._state[1], o._state[2]}
|
||||
@@ -159,7 +205,11 @@ public:
|
||||
}
|
||||
}
|
||||
//! Move construct the derived implementation.
|
||||
string_ref(string_ref &&o) noexcept : _begin(o._begin), _end(o._end), _state{o._state[0], o._state[1], o._state[2]}, _thunk(o._thunk)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 string_ref(string_ref &&o) noexcept
|
||||
: _begin(o._begin)
|
||||
, _end(o._end)
|
||||
, _state{o._state[0], o._state[1], o._state[2]}
|
||||
, _thunk(o._thunk)
|
||||
{
|
||||
if(_thunk != nullptr)
|
||||
{
|
||||
@@ -167,7 +217,7 @@ public:
|
||||
}
|
||||
}
|
||||
//! Copy assignment
|
||||
string_ref &operator=(const string_ref &o)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 string_ref &operator=(const string_ref &o)
|
||||
{
|
||||
if(this != &o)
|
||||
{
|
||||
@@ -191,7 +241,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
//! Move assignment
|
||||
string_ref &operator=(string_ref &&o) noexcept
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 string_ref &operator=(string_ref &&o) noexcept
|
||||
{
|
||||
if(this != &o)
|
||||
{
|
||||
@@ -201,7 +251,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
//! Destruction
|
||||
~string_ref()
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 ~string_ref()
|
||||
{
|
||||
if(_thunk != nullptr)
|
||||
{
|
||||
@@ -211,25 +261,25 @@ public:
|
||||
}
|
||||
|
||||
//! Returns whether the reference is empty or not
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD bool empty() const noexcept { return _begin == _end; }
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD constexpr bool empty() const noexcept { return _begin == _end; }
|
||||
//! Returns the size of the string
|
||||
size_type size() const noexcept { return _end - _begin; }
|
||||
constexpr size_type size() const noexcept { return _end - _begin; }
|
||||
//! Returns a null terminated C string
|
||||
const_pointer c_str() const noexcept { return _begin; }
|
||||
constexpr const_pointer c_str() const noexcept { return _begin; }
|
||||
//! Returns a null terminated C string
|
||||
const_pointer data() const noexcept { return _begin; }
|
||||
constexpr const_pointer data() const noexcept { return _begin; }
|
||||
//! Returns the beginning of the string
|
||||
iterator begin() noexcept { return _begin; }
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 iterator begin() noexcept { return _begin; }
|
||||
//! Returns the beginning of the string
|
||||
const_iterator begin() const noexcept { return _begin; }
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 const_iterator begin() const noexcept { return _begin; }
|
||||
//! Returns the beginning of the string
|
||||
const_iterator cbegin() const noexcept { return _begin; }
|
||||
constexpr const_iterator cbegin() const noexcept { return _begin; }
|
||||
//! Returns the end of the string
|
||||
iterator end() noexcept { return _end; }
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 iterator end() noexcept { return _end; }
|
||||
//! Returns the end of the string
|
||||
const_iterator end() const noexcept { return _end; }
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 const_iterator end() const noexcept { return _end; }
|
||||
//! Returns the end of the string
|
||||
const_iterator cend() const noexcept { return _end; }
|
||||
constexpr const_iterator cend() const noexcept { return _end; }
|
||||
};
|
||||
|
||||
/*! A reference counted, threadsafe reference to a message string.
|
||||
@@ -243,13 +293,13 @@ public:
|
||||
_allocated_msg *&_msg() noexcept { return reinterpret_cast<_allocated_msg *&>(this->_state[0]); } // NOLINT
|
||||
const _allocated_msg *_msg() const noexcept { return reinterpret_cast<const _allocated_msg *>(this->_state[0]); } // NOLINT
|
||||
|
||||
static void _refcounted_string_thunk(string_ref *_dest, const string_ref *_src, _thunk_op op) noexcept
|
||||
static BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 void _refcounted_string_thunk(string_ref *_dest, const string_ref *_src, _thunk_op op) noexcept
|
||||
{
|
||||
auto dest = static_cast<atomic_refcounted_string_ref *>(_dest); // NOLINT
|
||||
auto dest = static_cast<atomic_refcounted_string_ref *>(_dest); // NOLINT
|
||||
auto src = static_cast<const atomic_refcounted_string_ref *>(_src); // NOLINT
|
||||
(void) src;
|
||||
assert(dest->_thunk == _refcounted_string_thunk); // NOLINT
|
||||
assert(src == nullptr || src->_thunk == _refcounted_string_thunk); // NOLINT
|
||||
assert(dest->_thunk == _refcounted_string_thunk); // NOLINT
|
||||
assert(src == nullptr || src->_thunk == _refcounted_string_thunk); // NOLINT
|
||||
switch(op)
|
||||
{
|
||||
case _thunk_op::copy:
|
||||
@@ -264,7 +314,7 @@ public:
|
||||
}
|
||||
case _thunk_op::move:
|
||||
{
|
||||
assert(src); // NOLINT
|
||||
assert(src); // NOLINT
|
||||
auto msrc = const_cast<atomic_refcounted_string_ref *>(src); // NOLINT
|
||||
msrc->_begin = msrc->_end = nullptr;
|
||||
msrc->_state[0] = msrc->_state[1] = msrc->_state[2] = nullptr;
|
||||
@@ -279,7 +329,7 @@ public:
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
free((void *) dest->_begin); // NOLINT
|
||||
delete dest->_msg(); // NOLINT
|
||||
delete dest->_msg(); // NOLINT
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,7 +338,8 @@ public:
|
||||
|
||||
public:
|
||||
//! Construct from a C string literal allocated using `malloc()`.
|
||||
explicit atomic_refcounted_string_ref(const char *str, size_type len = static_cast<size_type>(-1), void *state1 = nullptr, void *state2 = nullptr) noexcept : string_ref(str, len, new(std::nothrow) _allocated_msg, state1, state2, _refcounted_string_thunk)
|
||||
explicit atomic_refcounted_string_ref(const char *str, size_type len = static_cast<size_type>(-1), void *state1 = nullptr, void *state2 = nullptr) noexcept
|
||||
: string_ref(str, len, new(std::nothrow) _allocated_msg, state1, state2, _refcounted_string_thunk)
|
||||
{
|
||||
if(_msg() == nullptr)
|
||||
{
|
||||
@@ -309,7 +360,26 @@ protected:
|
||||
|
||||
Do NOT make up your own value. Do NOT use zero.
|
||||
*/
|
||||
constexpr explicit status_code_domain(unique_id_type id) noexcept : _id(id) {}
|
||||
constexpr explicit status_code_domain(unique_id_type id) noexcept
|
||||
: _id(id)
|
||||
{
|
||||
}
|
||||
/*! UUID constructor, where input is constexpr parsed into a `unique_id_type`.
|
||||
*/
|
||||
template <size_t N>
|
||||
constexpr explicit status_code_domain(const char (&uuid)[N]) noexcept
|
||||
: _id(detail::parse_uuid_from_array<N>(uuid))
|
||||
{
|
||||
}
|
||||
template <size_t N> struct _uuid_size
|
||||
{
|
||||
};
|
||||
//! Alternative UUID constructor
|
||||
template <size_t N>
|
||||
constexpr explicit status_code_domain(const char *uuid, _uuid_size<N> /*unused*/) noexcept
|
||||
: _id(detail::parse_uuid_from_pointer<N>(uuid))
|
||||
{
|
||||
}
|
||||
//! No public copying at type erased level
|
||||
status_code_domain(const status_code_domain &) = default;
|
||||
//! No public moving at type erased level
|
||||
@@ -332,31 +402,60 @@ public:
|
||||
//! Returns the unique id used to identify identical category instances.
|
||||
constexpr unique_id_type id() const noexcept { return _id; }
|
||||
//! Name of this category.
|
||||
virtual string_ref name() const noexcept = 0;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual string_ref name() const noexcept = 0;
|
||||
//! Information about the payload of the code for this domain
|
||||
struct payload_info_t
|
||||
{
|
||||
size_t payload_size{0}; //!< The payload size in bytes
|
||||
size_t total_size{0}; //!< The total status code size in bytes (includes domain pointer and mixins state)
|
||||
size_t total_alignment{1}; //!< The total status code alignment in bytes
|
||||
|
||||
payload_info_t() = default;
|
||||
constexpr payload_info_t(size_t _payload_size, size_t _total_size, size_t _total_alignment)
|
||||
: payload_size(_payload_size)
|
||||
, total_size(_total_size)
|
||||
, total_alignment(_total_alignment)
|
||||
{
|
||||
}
|
||||
};
|
||||
//! Information about this domain's payload
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual payload_info_t payload_info() const noexcept = 0;
|
||||
|
||||
protected:
|
||||
//! True if code means failure.
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept = 0;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual bool _do_failure(const status_code<void> &code) const noexcept = 0;
|
||||
//! True if code is (potentially non-transitively) equivalent to another code in another domain.
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept = 0;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept = 0;
|
||||
//! Returns the generic code closest to this code, if any.
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept = 0;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual generic_code _generic_code(const status_code<void> &code) const noexcept = 0;
|
||||
//! Return a reference to a string textually representing a code.
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept = 0;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual string_ref _do_message(const status_code<void> &code) const noexcept = 0;
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
//! Throw a code as a C++ exception.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const = 0;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual void _do_throw_exception(const status_code<void> &code) const = 0;
|
||||
#else
|
||||
// Keep a vtable slot for binary compatibility
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> & /*code*/) const { abort(); }
|
||||
#endif
|
||||
// For a `status_code<erased<T>>` only, copy from `src` to `dst`. Default implementation uses `memcpy()`.
|
||||
virtual void _do_erased_copy(status_code<void> &dst, const status_code<void> &src, size_t bytes) const { memcpy(&dst, &src, bytes); } // NOLINT
|
||||
// For a `status_code<erased<T>>` only, copy from `src` to `dst`. Default implementation uses `memcpy()`. You should return false here if your payload is not
|
||||
// trivially copyable or would not fit.
|
||||
virtual bool _do_erased_copy(status_code<void> &dst, const status_code<void> &src, payload_info_t dstinfo) const
|
||||
{
|
||||
// Note that dst may not have its domain set
|
||||
const auto srcinfo = payload_info();
|
||||
if(dstinfo.total_size < srcinfo.total_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const auto tocopy = (dstinfo.total_size > srcinfo.total_size) ? srcinfo.total_size : dstinfo.total_size;
|
||||
memcpy(&dst, &src, tocopy);
|
||||
return true;
|
||||
} // NOLINT
|
||||
// For a `status_code<erased<T>>` only, destroy the erased value type. Default implementation does nothing.
|
||||
virtual void _do_erased_destroy(status_code<void> &code, size_t bytes) const noexcept // NOLINT
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 virtual void _do_erased_destroy(status_code<void> &code, payload_info_t info) const noexcept // NOLINT
|
||||
{
|
||||
(void) code;
|
||||
(void) bytes;
|
||||
(void) info;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018 - 2022 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_ERROR_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_ERROR_HPP
|
||||
|
||||
#include "status_code.hpp"
|
||||
|
||||
#include <exception> // for std::exception
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
/*! Exception type representing a thrown status_code
|
||||
*/
|
||||
template <class DomainType> class status_error;
|
||||
|
||||
/*! The erased type edition of status_error.
|
||||
*/
|
||||
template <> class status_error<void> : public std::exception
|
||||
{
|
||||
protected:
|
||||
//! Constructs an instance. Not publicly available.
|
||||
status_error() = default;
|
||||
//! Copy constructor. Not publicly available
|
||||
status_error(const status_error &) = default;
|
||||
//! Move constructor. Not publicly available
|
||||
status_error(status_error &&) = default;
|
||||
//! Copy assignment. Not publicly available
|
||||
status_error &operator=(const status_error &) = default;
|
||||
//! Move assignment. Not publicly available
|
||||
status_error &operator=(status_error &&) = default;
|
||||
//! Destructor. Not publicly available.
|
||||
~status_error() override = default;
|
||||
|
||||
virtual const status_code<void> &_do_code() const noexcept = 0;
|
||||
|
||||
public:
|
||||
//! The type of the status domain
|
||||
using domain_type = void;
|
||||
//! The type of the status code
|
||||
using status_code_type = status_code<void>;
|
||||
|
||||
public:
|
||||
//! The erased status code which generated this exception instance.
|
||||
const status_code<void> &code() const noexcept { return _do_code(); }
|
||||
};
|
||||
|
||||
/*! Exception type representing a thrown status_code
|
||||
*/
|
||||
template <class DomainType> class status_error : public status_error<void>
|
||||
{
|
||||
status_code<DomainType> _code;
|
||||
typename DomainType::string_ref _msgref;
|
||||
|
||||
virtual const status_code<void> &_do_code() const noexcept override final { return _code; }
|
||||
|
||||
public:
|
||||
//! The type of the status domain
|
||||
using domain_type = DomainType;
|
||||
//! The type of the status code
|
||||
using status_code_type = status_code<DomainType>;
|
||||
|
||||
//! Constructs an instance
|
||||
explicit status_error(status_code<DomainType> code)
|
||||
: _code(static_cast<status_code<DomainType> &&>(code))
|
||||
, _msgref(_code.message())
|
||||
{
|
||||
}
|
||||
|
||||
//! Return an explanatory string
|
||||
virtual const char *what() const noexcept override { return _msgref.c_str(); } // NOLINT
|
||||
|
||||
//! Returns a reference to the code
|
||||
const status_code_type &code() const & { return _code; }
|
||||
//! Returns a reference to the code
|
||||
status_code_type &code() & { return _code; }
|
||||
//! Returns a reference to the code
|
||||
const status_code_type &&code() const && { return _code; }
|
||||
//! Returns a reference to the code
|
||||
status_code_type &&code() && { return _code; }
|
||||
};
|
||||
|
||||
/*! Exception type representing a thrown erased status_code
|
||||
*/
|
||||
template <class ErasedType> class status_error<detail::erased<ErasedType>> : public status_error<void>
|
||||
{
|
||||
status_code<detail::erased<ErasedType>> _code;
|
||||
typename status_code_domain::string_ref _msgref;
|
||||
|
||||
virtual const status_code<detail::erased<ErasedType>> &_do_code() const noexcept override final { return _code; }
|
||||
|
||||
public:
|
||||
//! The type of the status domain
|
||||
using domain_type = void;
|
||||
//! The type of the status code
|
||||
using status_code_type = status_code<detail::erased<ErasedType>>;
|
||||
|
||||
//! Constructs an instance
|
||||
explicit status_error(status_code<detail::erased<ErasedType>> code)
|
||||
: _code(static_cast<status_code<detail::erased<ErasedType>> &&>(code))
|
||||
, _msgref(_code.message())
|
||||
{
|
||||
}
|
||||
|
||||
//! Return an explanatory string
|
||||
virtual const char *what() const noexcept override { return _msgref.c_str(); } // NOLINT
|
||||
|
||||
//! Returns a reference to the code
|
||||
const status_code_type &code() const & { return _code; }
|
||||
//! Returns a reference to the code
|
||||
status_code_type &code() & { return _code; }
|
||||
//! Returns a reference to the code
|
||||
const status_code_type &&code() const && { return _code; }
|
||||
//! Returns a reference to the code
|
||||
status_code_type &&code() && { return _code; }
|
||||
};
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,322 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018 - 2021 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Aug 2018
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License in the accompanying file
|
||||
Licence.txt or at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file Licence.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_STD_ERROR_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STD_ERROR_CODE_HPP
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
|
||||
#include "posix_code.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
#include "win32_code.hpp"
|
||||
#endif
|
||||
|
||||
#include <system_error>
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
class _std_error_code_domain;
|
||||
//! A `status_code` representing exactly a `std::error_code`
|
||||
using std_error_code = status_code<_std_error_code_domain>;
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> struct mixin<Base, _std_error_code_domain> : public Base
|
||||
{
|
||||
using Base::Base;
|
||||
|
||||
//! Implicit constructor from a `std::error_code`
|
||||
inline mixin(std::error_code ec);
|
||||
|
||||
//! Returns the error code category
|
||||
inline const std::error_category &category() const noexcept;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
|
||||
/*! The implementation of the domain for `std::error_code` error codes.
|
||||
*/
|
||||
class _std_error_code_domain final : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
using _error_code_type = std::error_code;
|
||||
using _error_category_type = std::error_category;
|
||||
|
||||
std::string _name;
|
||||
|
||||
static _base::string_ref _make_string_ref(_error_code_type c) noexcept
|
||||
{
|
||||
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
||||
try
|
||||
#endif
|
||||
{
|
||||
std::string msg = c.message();
|
||||
auto *p = static_cast<char *>(malloc(msg.size() + 1)); // NOLINT
|
||||
if(p == nullptr)
|
||||
{
|
||||
return _base::string_ref("failed to allocate message");
|
||||
}
|
||||
memcpy(p, msg.c_str(), msg.size() + 1);
|
||||
return _base::atomic_refcounted_string_ref(p, msg.size());
|
||||
}
|
||||
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
||||
catch(...)
|
||||
{
|
||||
return _base::string_ref("failed to allocate message");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
//! The value type of the `std::error_code` code, which stores the `int` from the `std::error_code`
|
||||
using value_type = int;
|
||||
using _base::string_ref;
|
||||
|
||||
//! Returns the error category singleton pointer this status code domain represents
|
||||
const _error_category_type &error_category() const noexcept
|
||||
{
|
||||
auto ptr = 0x223a160d20de97b4 ^ this->id();
|
||||
return *reinterpret_cast<const _error_category_type *>(ptr);
|
||||
}
|
||||
|
||||
//! Default constructor
|
||||
explicit _std_error_code_domain(const _error_category_type &category) noexcept
|
||||
: _base(0x223a160d20de97b4 ^ reinterpret_cast<_base::unique_id_type>(&category))
|
||||
, _name("std_error_code_domain(")
|
||||
{
|
||||
_name.append(category.name());
|
||||
_name.push_back(')');
|
||||
}
|
||||
_std_error_code_domain(const _std_error_code_domain &) = default;
|
||||
_std_error_code_domain(_std_error_code_domain &&) = default;
|
||||
_std_error_code_domain &operator=(const _std_error_code_domain &) = default;
|
||||
_std_error_code_domain &operator=(_std_error_code_domain &&) = default;
|
||||
~_std_error_code_domain() = default;
|
||||
|
||||
static inline const _std_error_code_domain *get(_error_code_type ec);
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref(_name.c_str(), _name.size()); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override;
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override;
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override;
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override;
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override;
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
extern inline _std_error_code_domain *std_error_code_domain_from_category(const std::error_category &category)
|
||||
{
|
||||
static constexpr size_t max_items = 64;
|
||||
static struct storage_t
|
||||
{
|
||||
std::atomic<unsigned> _lock;
|
||||
union item_t
|
||||
{
|
||||
int _init;
|
||||
_std_error_code_domain domain;
|
||||
constexpr item_t()
|
||||
: _init(0)
|
||||
{
|
||||
}
|
||||
~item_t() {}
|
||||
} items[max_items];
|
||||
size_t count{0};
|
||||
|
||||
void lock()
|
||||
{
|
||||
while(_lock.exchange(1, std::memory_order_acquire) != 0)
|
||||
;
|
||||
}
|
||||
void unlock() { _lock.store(0, std::memory_order_release); }
|
||||
|
||||
storage_t() {}
|
||||
~storage_t()
|
||||
{
|
||||
lock();
|
||||
for(size_t n = 0; n < count; n++)
|
||||
{
|
||||
items[n].domain.~_std_error_code_domain();
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
_std_error_code_domain *add(const std::error_category &category)
|
||||
{
|
||||
_std_error_code_domain *ret = nullptr;
|
||||
lock();
|
||||
for(size_t n = 0; n < count; n++)
|
||||
{
|
||||
if(items[n].domain.error_category() == category)
|
||||
{
|
||||
ret = &items[n].domain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ret == nullptr && count < max_items)
|
||||
{
|
||||
ret = new(std::addressof(items[count++].domain)) _std_error_code_domain(category);
|
||||
}
|
||||
unlock();
|
||||
return ret;
|
||||
}
|
||||
} storage;
|
||||
return storage.add(category);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base>
|
||||
inline mixin<Base, _std_error_code_domain>::mixin(std::error_code ec)
|
||||
: Base(typename Base::_value_type_constructor{}, _std_error_code_domain::get(ec), ec.value())
|
||||
{
|
||||
}
|
||||
|
||||
template <class Base> inline const std::error_category &mixin<Base, _std_error_code_domain>::category() const noexcept
|
||||
{
|
||||
const auto &domain = static_cast<const _std_error_code_domain &>(this->domain());
|
||||
return domain.error_category();
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
inline const _std_error_code_domain *_std_error_code_domain::get(std::error_code ec)
|
||||
{
|
||||
auto *p = detail::std_error_code_domain_from_category(ec.category());
|
||||
assert(p != nullptr);
|
||||
if(p == nullptr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
inline bool _std_error_code_domain::_do_failure(const status_code<void> &code) const noexcept
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
return static_cast<const std_error_code &>(code).value() != 0; // NOLINT
|
||||
}
|
||||
|
||||
inline bool _std_error_code_domain::_do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept
|
||||
{
|
||||
assert(code1.domain() == *this);
|
||||
const auto &c1 = static_cast<const std_error_code &>(code1); // NOLINT
|
||||
const auto &cat1 = c1.category();
|
||||
// Are we comparing to another wrapped error_code?
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const std_error_code &>(code2); // NOLINT
|
||||
const auto &cat2 = c2.category();
|
||||
// If the error code categories are identical, do literal comparison
|
||||
if(cat1 == cat2)
|
||||
{
|
||||
return c1.value() == c2.value();
|
||||
}
|
||||
// Otherwise fall back onto the _generic_code comparison, which uses default_error_condition()
|
||||
return false;
|
||||
}
|
||||
// Am I an error code with generic category?
|
||||
if(cat1 == std::generic_category())
|
||||
{
|
||||
// Convert to generic code, and compare that
|
||||
generic_code _c1(static_cast<errc>(c1.value()));
|
||||
return _c1 == code2;
|
||||
}
|
||||
// Am I an error code with system category?
|
||||
if(cat1 == std::system_category())
|
||||
{
|
||||
// Convert to POSIX or Win32 code, and compare that
|
||||
#ifdef _WIN32
|
||||
win32_code _c1((win32::DWORD) c1.value());
|
||||
return _c1 == code2;
|
||||
#elif !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX)
|
||||
posix_code _c1(c1.value());
|
||||
return _c1 == code2;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline generic_code _std_error_code_domain::_generic_code(const status_code<void> &code) const noexcept
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const std_error_code &>(code); // NOLINT
|
||||
// Ask my embedded error code for its mapping to std::errc, which is a subset of our generic_code errc.
|
||||
std::error_condition cond(c.category().default_error_condition(c.value()));
|
||||
if(cond.category() == std::generic_category())
|
||||
{
|
||||
return generic_code(static_cast<errc>(cond.value()));
|
||||
}
|
||||
#if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX) && !defined(_WIN32)
|
||||
if(cond.category() == std::system_category())
|
||||
{
|
||||
return generic_code(static_cast<errc>(cond.value()));
|
||||
}
|
||||
#endif
|
||||
return errc::unknown;
|
||||
}
|
||||
|
||||
inline _std_error_code_domain::string_ref _std_error_code_domain::_do_message(const status_code<void> &code) const noexcept
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const std_error_code &>(code); // NOLINT
|
||||
return _make_string_ref(_error_code_type(c.value(), c.category()));
|
||||
}
|
||||
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN inline void _std_error_code_domain::_do_throw_exception(const status_code<void> &code) const
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const std_error_code &>(code); // NOLINT
|
||||
throw std::system_error(std::error_code(c.value(), c.category()));
|
||||
}
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(std_error_code) <= sizeof(void *) * 2, "std_error_code does not fit into a system_code!");
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
// Enable implicit construction of `std_error_code` from `std::error_code`.
|
||||
namespace std
|
||||
{
|
||||
inline BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::std_error_code make_status_code(error_code c) noexcept
|
||||
{
|
||||
return BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::std_error_code(c);
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -31,7 +31,11 @@ DEALINGS IN THE SOFTWARE.
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_SYSTEM_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_SYSTEM_CODE_HPP
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
|
||||
#include "posix_code.hpp"
|
||||
#else
|
||||
#include "quick_status_code_from_enum.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
#include "nt_code.hpp"
|
||||
@@ -54,11 +58,11 @@ For POSIX, `posix_code` is possible.
|
||||
You are guaranteed that `system_code` can be transported by the compiler
|
||||
in exactly two CPU registers.
|
||||
*/
|
||||
using system_code = status_code<erased<intptr_t>>;
|
||||
using system_code = erased_status_code<intptr_t>;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static_assert(sizeof(system_code) == 2 * sizeof(void *), "system_code is not exactly two pointers in size!");
|
||||
static_assert(traits::is_move_relocating<system_code>::value, "system_code is not move relocating!");
|
||||
static_assert(traits::is_move_bitcopying<system_code>::value, "system_code is not move bitcopying!");
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: June 2018
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "system_code.hpp"
|
||||
|
||||
#include "status_error.hpp"
|
||||
|
||||
#include <exception> // for exception_ptr
|
||||
#include <stdexcept> // for the exception types
|
||||
#include <system_error> // for std::system_error
|
||||
@@ -50,7 +52,31 @@ inline system_code system_code_from_exception(std::exception_ptr &&ep = std::cur
|
||||
}
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(ep);
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(ep);
|
||||
}
|
||||
catch(const status_error<void> &e)
|
||||
{
|
||||
try
|
||||
{
|
||||
system_code erased(e.code());
|
||||
if(!erased.empty())
|
||||
{
|
||||
return erased;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// Source status code's do_erased_copy() routine refused to copy the original
|
||||
// Process instead as if the source were not a status_error
|
||||
}
|
||||
throw;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(const std::invalid_argument & /*unused*/)
|
||||
{
|
||||
@@ -89,7 +115,11 @@ inline system_code system_code_from_exception(std::exception_ptr &&ep = std::cur
|
||||
#ifdef _WIN32
|
||||
return win32_code(e.code().value());
|
||||
#else
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
|
||||
return posix_code(e.code().value());
|
||||
#else
|
||||
return generic_code(static_cast<errc>(e.code().value()));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
// Don't know this error code category, can't wrap it into std_error_code
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#error This file should only be included on Windows
|
||||
#endif
|
||||
|
||||
#include "generic_code.hpp"
|
||||
#include "quick_status_code_from_enum.hpp"
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
@@ -45,12 +45,29 @@ namespace win32
|
||||
// A Win32 DWORD
|
||||
using DWORD = unsigned long;
|
||||
// Used to retrieve the current Win32 error code
|
||||
extern "C" DWORD __stdcall GetLastError();
|
||||
extern DWORD __stdcall GetLastError();
|
||||
// Used to retrieve a locale-specific message string for some error code
|
||||
extern "C" DWORD __stdcall FormatMessageW(DWORD dwFlags, const void *lpSource, DWORD dwMessageId, DWORD dwLanguageId, wchar_t *lpBuffer, DWORD nSize, void /*va_list*/ *Arguments);
|
||||
extern DWORD __stdcall FormatMessageW(DWORD dwFlags, const void *lpSource, DWORD dwMessageId, DWORD dwLanguageId, wchar_t *lpBuffer, DWORD nSize,
|
||||
void /*va_list*/ *Arguments);
|
||||
// Converts UTF-16 message string to UTF-8
|
||||
extern "C" int __stdcall WideCharToMultiByte(unsigned int CodePage, DWORD dwFlags, const wchar_t *lpWideCharStr, int cchWideChar, char *lpMultiByteStr, int cbMultiByte, const char *lpDefaultChar, int *lpUsedDefaultChar);
|
||||
extern int __stdcall WideCharToMultiByte(unsigned int CodePage, DWORD dwFlags, const wchar_t *lpWideCharStr, int cchWideChar, char *lpMultiByteStr,
|
||||
int cbMultiByte, const char *lpDefaultChar, int *lpUsedDefaultChar);
|
||||
#pragma comment(lib, "kernel32.lib")
|
||||
#if(defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64))
|
||||
#pragma comment(linker, "/alternatename:?GetLastError@win32@system_error2@@YAKXZ=GetLastError")
|
||||
#pragma comment(linker, "/alternatename:?FormatMessageW@win32@system_error2@@YAKKPEBXKKPEA_WKPEAX@Z=FormatMessageW")
|
||||
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@system_error2@@YAHIKPEB_WHPEADHPEBDPEAH@Z=WideCharToMultiByte")
|
||||
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
|
||||
#pragma comment(linker, "/alternatename:?GetLastError@win32@system_error2@@YGKXZ=_GetLastError@0")
|
||||
#pragma comment(linker, "/alternatename:?FormatMessageW@win32@system_error2@@YGKKPBXKKPA_WKPAX@Z=_FormatMessageW@28")
|
||||
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@system_error2@@YGHIKPB_WHPADHPBDPAH@Z=_WideCharToMultiByte@32")
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
#pragma comment(linker, "/alternatename:?GetLastError@win32@system_error2@@YAKXZ=GetLastError")
|
||||
#pragma comment(linker, "/alternatename:?FormatMessageW@win32@system_error2@@YAKKPBXKKPA_WKPAX@Z=FormatMessageW")
|
||||
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@system_error2@@YAHIKPB_WHPADHPBDPAH@Z=WideCharToMultiByte")
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
} // namespace win32
|
||||
|
||||
class _win32_code_domain;
|
||||
@@ -60,12 +77,23 @@ using win32_code = status_code<_win32_code_domain>;
|
||||
//! (Windows only) A specialisation of `status_error` for the Win32 error code domain.
|
||||
using win32_error = status_error<_win32_code_domain>;
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> struct mixin<Base, _win32_code_domain> : public Base
|
||||
{
|
||||
using Base::Base;
|
||||
|
||||
//! Returns a `win32_code` for the current value of `GetLastError()`.
|
||||
static inline win32_code current() noexcept;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
/*! (Windows only) The implementation of the domain for Win32 error codes, those returned by `GetLastError()`.
|
||||
*/
|
||||
*/
|
||||
class _win32_code_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode> friend class detail::indirecting_domain;
|
||||
template <class StatusCode, class Allocator> friend class detail::indirecting_domain;
|
||||
friend class _com_code_domain;
|
||||
using _base = status_code_domain;
|
||||
static int _win32_code_to_errno(win32::DWORD c)
|
||||
@@ -82,7 +110,8 @@ class _win32_code_domain : public status_code_domain
|
||||
static _base::string_ref _make_string_ref(win32::DWORD c) noexcept
|
||||
{
|
||||
wchar_t buffer[32768];
|
||||
win32::DWORD wlen = win32::FormatMessageW(0x00001000 /*FORMAT_MESSAGE_FROM_SYSTEM*/ | 0x00000200 /*FORMAT_MESSAGE_IGNORE_INSERTS*/, nullptr, c, 0, buffer, 32768, nullptr);
|
||||
win32::DWORD wlen =
|
||||
win32::FormatMessageW(0x00001000 /*FORMAT_MESSAGE_FROM_SYSTEM*/ | 0x00000200 /*FORMAT_MESSAGE_IGNORE_INSERTS*/, nullptr, c, 0, buffer, 32768, nullptr);
|
||||
size_t allocation = wlen + (wlen >> 1);
|
||||
win32::DWORD bytes;
|
||||
if(wlen == 0)
|
||||
@@ -124,7 +153,10 @@ public:
|
||||
|
||||
public:
|
||||
//! Default constructor
|
||||
constexpr explicit _win32_code_domain(typename _base::unique_id_type id = 0x8cd18ee72d680f1b) noexcept : _base(id) {}
|
||||
constexpr explicit _win32_code_domain(typename _base::unique_id_type id = 0x8cd18ee72d680f1b) noexcept
|
||||
: _base(id)
|
||||
{
|
||||
}
|
||||
_win32_code_domain(const _win32_code_domain &) = default;
|
||||
_win32_code_domain(_win32_code_domain &&) = default;
|
||||
_win32_code_domain &operator=(const _win32_code_domain &) = default;
|
||||
@@ -135,6 +167,13 @@ public:
|
||||
static inline constexpr const _win32_code_domain &get();
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref("win32 domain"); } // NOLINT
|
||||
|
||||
virtual payload_info_t payload_info() const noexcept override
|
||||
{
|
||||
return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
|
||||
(alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
@@ -188,6 +227,14 @@ inline constexpr const _win32_code_domain &_win32_code_domain::get()
|
||||
return win32_code_domain;
|
||||
}
|
||||
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base> inline win32_code mixin<Base, _win32_code_domain>::current() noexcept
|
||||
{
|
||||
return win32_code(win32::GetLastError());
|
||||
}
|
||||
} // namespace mixins
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,502 +0,0 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_STATUS_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_CODE_HPP
|
||||
|
||||
#include "status_code_domain.hpp"
|
||||
|
||||
#if __cplusplus >= 201700 || _HAS_CXX17
|
||||
// 0.26
|
||||
#include <utility> // for in_place
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
using in_place_t = std::in_place_t;
|
||||
using std::in_place;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#else
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
//! Aliases `std::in_place_t` if on C++ 17 or later, else defined locally.
|
||||
struct in_place_t
|
||||
{
|
||||
explicit in_place_t() = default;
|
||||
};
|
||||
//! Aliases `std::in_place` if on C++ 17 or later, else defined locally.
|
||||
constexpr in_place_t in_place{};
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
//! Namespace for user injected mixins
|
||||
namespace mixins
|
||||
{
|
||||
template <class Base, class T> struct mixin : public Base
|
||||
{
|
||||
using Base::Base;
|
||||
};
|
||||
} // namespace mixins
|
||||
|
||||
/*! A tag for an erased value type for `status_code<D>`.
|
||||
Available only if `ErasedType` satisfies `traits::is_move_relocating<ErasedType>::value`.
|
||||
*/
|
||||
template <class ErasedType, //
|
||||
typename std::enable_if<traits::is_move_relocating<ErasedType>::value, bool>::type = true>
|
||||
struct erased
|
||||
{
|
||||
using value_type = ErasedType;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T> struct is_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_status_code<status_code<T>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <class T> struct is_erased_status_code
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <class T> struct is_erased_status_code<status_code<erased<T>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
// From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4436.pdf
|
||||
namespace impl
|
||||
{
|
||||
template <typename... Ts> struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
|
||||
template <class...> struct types
|
||||
{
|
||||
using type = types;
|
||||
};
|
||||
template <template <class...> class T, class types, class = void> struct test_apply
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <template <class...> class T, class... Ts> struct test_apply<T, types<Ts...>, void_t<T<Ts...>>>
|
||||
{
|
||||
using type = T<Ts...>;
|
||||
};
|
||||
} // namespace impl
|
||||
template <template <class...> class T, class... Ts> using test_apply = impl::test_apply<T, impl::types<Ts...>>;
|
||||
|
||||
template <class T, class... Args> using get_make_status_code_result = decltype(make_status_code(std::declval<T>(), std::declval<Args>()...));
|
||||
template <class... Args> using safe_get_make_status_code_result = test_apply<get_make_status_code_result, Args...>;
|
||||
} // namespace detail
|
||||
|
||||
//! Trait returning true if the type is a status code.
|
||||
template <class T> struct is_status_code
|
||||
{
|
||||
static constexpr bool value = detail::is_status_code<typename std::decay<T>::type>::value || detail::is_erased_status_code<typename std::decay<T>::type>::value;
|
||||
};
|
||||
|
||||
/*! A type erased lightweight status code reflecting empty, success, or failure.
|
||||
Differs from `status_code<erased<>>` by being always available irrespective of
|
||||
the domain's value type, but cannot be copied, moved, nor destructed. Thus one
|
||||
always passes this around by const lvalue reference.
|
||||
*/
|
||||
template <> class status_code<void>
|
||||
{
|
||||
template <class T> friend class status_code;
|
||||
|
||||
public:
|
||||
//! The type of the domain.
|
||||
using domain_type = void;
|
||||
//! The type of the status code.
|
||||
using value_type = void;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename status_code_domain::string_ref;
|
||||
|
||||
protected:
|
||||
const status_code_domain *_domain{nullptr};
|
||||
|
||||
protected:
|
||||
//! No default construction at type erased level
|
||||
status_code() = default;
|
||||
//! No public copying at type erased level
|
||||
status_code(const status_code &) = default;
|
||||
//! No public moving at type erased level
|
||||
status_code(status_code &&) = default;
|
||||
//! No public assignment at type erased level
|
||||
status_code &operator=(const status_code &) = default;
|
||||
//! No public assignment at type erased level
|
||||
status_code &operator=(status_code &&) = default;
|
||||
//! No public destruction at type erased level
|
||||
~status_code() = default;
|
||||
|
||||
//! Used to construct a non-empty type erased status code
|
||||
constexpr explicit status_code(const status_code_domain *v) noexcept : _domain(v) {}
|
||||
|
||||
public:
|
||||
//! Return the status code domain.
|
||||
constexpr const status_code_domain &domain() const noexcept { return *_domain; }
|
||||
//! True if the status code is empty.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD constexpr bool empty() const noexcept { return _domain == nullptr; }
|
||||
|
||||
//! Return a reference to a string textually representing a code.
|
||||
string_ref message() const noexcept { return (_domain != nullptr) ? _domain->_do_message(*this) : string_ref("(empty)"); }
|
||||
//! True if code means success.
|
||||
bool success() const noexcept { return (_domain != nullptr) ? !_domain->_do_failure(*this) : false; }
|
||||
//! True if code means failure.
|
||||
bool failure() const noexcept { return (_domain != nullptr) ? _domain->_do_failure(*this) : false; }
|
||||
/*! True if code is strictly (and potentially non-transitively) semantically equivalent to another code in another domain.
|
||||
Note that usually non-semantic i.e. pure value comparison is used when the other status code has the same domain.
|
||||
As `equivalent()` will try mapping to generic code, this usually captures when two codes have the same semantic
|
||||
meaning in `equivalent()`.
|
||||
*/
|
||||
template <class T> bool strictly_equivalent(const status_code<T> &o) const noexcept
|
||||
{
|
||||
if(_domain && o._domain)
|
||||
{
|
||||
return _domain->_do_equivalent(*this, o);
|
||||
}
|
||||
// If we are both empty, we are equivalent
|
||||
if(!_domain && !o._domain)
|
||||
{
|
||||
return true; // NOLINT
|
||||
}
|
||||
// Otherwise not equivalent
|
||||
return false;
|
||||
}
|
||||
/*! True if code is equivalent, by any means, to another code in another domain (guaranteed transitive).
|
||||
Firstly `strictly_equivalent()` is run in both directions. If neither succeeds, each domain is asked
|
||||
for the equivalent generic code and those are compared.
|
||||
*/
|
||||
template <class T> inline bool equivalent(const status_code<T> &o) const noexcept;
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
//! Throw a code as a C++ exception.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN void throw_exception() const { _domain->_do_throw_exception(*this); }
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class DomainType> struct get_domain_value_type
|
||||
{
|
||||
using domain_type = DomainType;
|
||||
using value_type = typename domain_type::value_type;
|
||||
};
|
||||
template <class ErasedType> struct get_domain_value_type<erased<ErasedType>>
|
||||
{
|
||||
using domain_type = status_code_domain;
|
||||
using value_type = ErasedType;
|
||||
};
|
||||
template <class DomainType> class status_code_storage : public status_code<void>
|
||||
{
|
||||
using _base = status_code<void>;
|
||||
|
||||
public:
|
||||
//! The type of the domain.
|
||||
using domain_type = typename get_domain_value_type<DomainType>::domain_type;
|
||||
//! The type of the status code.
|
||||
using value_type = typename get_domain_value_type<DomainType>::value_type;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename domain_type::string_ref;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static_assert(std::is_move_constructible<value_type>::value || std::is_copy_constructible<value_type>::value, "DomainType::value_type is neither move nor copy constructible!");
|
||||
static_assert(!std::is_default_constructible<value_type>::value || std::is_nothrow_default_constructible<value_type>::value, "DomainType::value_type is not nothrow default constructible!");
|
||||
static_assert(!std::is_move_constructible<value_type>::value || std::is_nothrow_move_constructible<value_type>::value, "DomainType::value_type is not nothrow move constructible!");
|
||||
static_assert(std::is_nothrow_destructible<value_type>::value, "DomainType::value_type is not nothrow destructible!");
|
||||
#endif
|
||||
|
||||
// Replace the type erased implementations with type aware implementations for better codegen
|
||||
//! Return the status code domain.
|
||||
constexpr const domain_type &domain() const noexcept { return *static_cast<const domain_type *>(this->_domain); }
|
||||
|
||||
//! Reset the code to empty.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 void clear() noexcept
|
||||
{
|
||||
this->_value.~value_type();
|
||||
this->_domain = nullptr;
|
||||
new(&this->_value) value_type();
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr value_type &value() & noexcept { return this->_value; }
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr value_type &&value() && noexcept { return this->_value; }
|
||||
#endif
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr const value_type &value() const &noexcept { return this->_value; }
|
||||
//! Return a reference to the `value_type`.
|
||||
constexpr const value_type &&value() const &&noexcept { return this->_value; }
|
||||
|
||||
protected:
|
||||
status_code_storage() = default;
|
||||
status_code_storage(const status_code_storage &) = default;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code_storage(status_code_storage &&o) noexcept : _base(static_cast<status_code_storage &&>(o)), _value(static_cast<status_code_storage &&>(o)._value) { o._domain = nullptr; }
|
||||
status_code_storage &operator=(const status_code_storage &) = default;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code_storage &operator=(status_code_storage &&o) noexcept
|
||||
{
|
||||
this->~status_code_storage();
|
||||
new(this) status_code_storage(static_cast<status_code_storage &&>(o));
|
||||
return *this;
|
||||
}
|
||||
~status_code_storage() = default;
|
||||
|
||||
value_type _value{};
|
||||
struct _value_type_constructor
|
||||
{
|
||||
};
|
||||
template <class... Args>
|
||||
constexpr status_code_storage(_value_type_constructor /*unused*/, const status_code_domain *v, Args &&... args)
|
||||
: _base(v)
|
||||
, _value(static_cast<Args &&>(args)...)
|
||||
{
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/*! A lightweight, typed, status code reflecting empty, success, or failure.
|
||||
This is the main workhorse of the system_error2 library. Its characteristics reflect the value type
|
||||
set by its domain type, so if that value type is move-only or trivial, so is this.
|
||||
|
||||
An ADL discovered helper function `make_status_code(T, Args...)` is looked up by one of the constructors.
|
||||
If it is found, and it generates a status code compatible with this status code, implicit construction
|
||||
is made available.
|
||||
|
||||
You may mix in custom member functions and member function overrides by injecting a specialisation of
|
||||
`mixins::mixin<Base, YourDomainType>`. Your mixin must inherit from `Base`.
|
||||
*/
|
||||
template <class DomainType> class status_code : public mixins::mixin<detail::status_code_storage<DomainType>, DomainType>
|
||||
{
|
||||
template <class T> friend class status_code;
|
||||
using _base = mixins::mixin<detail::status_code_storage<DomainType>, DomainType>;
|
||||
|
||||
public:
|
||||
//! The type of the domain.
|
||||
using domain_type = DomainType;
|
||||
//! The type of the status code.
|
||||
using value_type = typename domain_type::value_type;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename domain_type::string_ref;
|
||||
|
||||
public:
|
||||
//! Default construction to empty
|
||||
status_code() = default;
|
||||
//! Copy constructor
|
||||
status_code(const status_code &) = default;
|
||||
//! Move constructor
|
||||
status_code(status_code &&) = default; // NOLINT
|
||||
//! Copy assignment
|
||||
status_code &operator=(const status_code &) = default;
|
||||
//! Move assignment
|
||||
status_code &operator=(status_code &&) = default; // NOLINT
|
||||
~status_code() = default;
|
||||
|
||||
//! Return a copy of the code.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code clone() const { return *this; }
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH ERRORED_STATUS_CODE *****/
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
template <class T, class... Args, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<!std::is_same<typename std::decay<T>::type, status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, in_place_t>::value // not in_place_t
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
|
||||
|
||||
bool>::type = true>
|
||||
constexpr status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
}
|
||||
//! Explicit in-place construction.
|
||||
template <class... Args>
|
||||
constexpr explicit status_code(in_place_t /*unused */, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args &&...>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), static_cast<Args &&>(args)...)
|
||||
{
|
||||
}
|
||||
//! Explicit in-place construction from initialiser list.
|
||||
template <class T, class... Args>
|
||||
constexpr explicit status_code(in_place_t /*unused */, std::initializer_list<T> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<T>, Args &&...>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), il, static_cast<Args &&>(args)...)
|
||||
{
|
||||
}
|
||||
//! Explicit copy construction from a `value_type`.
|
||||
constexpr explicit status_code(const value_type &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), v)
|
||||
{
|
||||
}
|
||||
//! Explicit move construction from a `value_type`.
|
||||
constexpr explicit status_code(value_type &&v) noexcept(std::is_nothrow_move_constructible<value_type>::value)
|
||||
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), static_cast<value_type &&>(v))
|
||||
{
|
||||
}
|
||||
/*! Explicit construction from an erased status code. Available only if
|
||||
`value_type` is trivially copyable or move relocating, and `sizeof(status_code) <= sizeof(status_code<erased<>>)`.
|
||||
Does not check if domains are equal.
|
||||
*/
|
||||
template <class ErasedType, //
|
||||
typename std::enable_if<detail::type_erasure_is_safe<ErasedType, value_type>::value, bool>::type = true>
|
||||
constexpr explicit status_code(const status_code<erased<ErasedType>> &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||
: status_code(detail::erasure_cast<value_type>(v.value()))
|
||||
{
|
||||
#if __cplusplus >= 201400
|
||||
assert(v.domain() == this->domain());
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Assignment from a `value_type`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code &operator=(const value_type &v) noexcept(std::is_nothrow_copy_assignable<value_type>::value)
|
||||
{
|
||||
this->_value = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Return a reference to a string textually representing a code.
|
||||
string_ref message() const noexcept { return this->_domain ? string_ref(this->domain()._do_message(*this)) : string_ref("(empty)"); }
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class DomainType> struct is_move_relocating<status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = is_move_relocating<typename DomainType::value_type>::value;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
|
||||
/*! Type erased, move-only status_code, unlike `status_code<void>` which cannot be moved nor destroyed. Available
|
||||
only if `erased<>` is available, which is when the domain's type is trivially
|
||||
copyable or is move relocatable, and if the size of the domain's typed error code is less than or equal to
|
||||
this erased error code. Copy construction is disabled, but if you want a copy call `.clone()`.
|
||||
|
||||
An ADL discovered helper function `make_status_code(T, Args...)` is looked up by one of the constructors.
|
||||
If it is found, and it generates a status code compatible with this status code, implicit construction
|
||||
is made available.
|
||||
*/
|
||||
template <class ErasedType> class status_code<erased<ErasedType>> : public mixins::mixin<detail::status_code_storage<erased<ErasedType>>, erased<ErasedType>>
|
||||
{
|
||||
template <class T> friend class status_code;
|
||||
using _base = mixins::mixin<detail::status_code_storage<erased<ErasedType>>, erased<ErasedType>>;
|
||||
|
||||
public:
|
||||
//! The type of the domain (void, as it is erased).
|
||||
using domain_type = void;
|
||||
//! The type of the erased status code.
|
||||
using value_type = ErasedType;
|
||||
//! The type of a reference to a message string.
|
||||
using string_ref = typename _base::string_ref;
|
||||
|
||||
public:
|
||||
//! Default construction to empty
|
||||
status_code() = default;
|
||||
//! Copy constructor
|
||||
status_code(const status_code &) = delete;
|
||||
//! Move constructor
|
||||
status_code(status_code &&) = default; // NOLINT
|
||||
//! Copy assignment
|
||||
status_code &operator=(const status_code &) = delete;
|
||||
//! Move assignment
|
||||
status_code &operator=(status_code &&) = default; // NOLINT
|
||||
~status_code()
|
||||
{
|
||||
if(nullptr != this->_domain)
|
||||
{
|
||||
this->_domain->_do_erased_destroy(*this, sizeof(*this));
|
||||
}
|
||||
}
|
||||
|
||||
//! Return a copy of the erased code by asking the domain to perform the erased copy.
|
||||
status_code clone() const
|
||||
{
|
||||
if(nullptr == this->_domain)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
status_code x;
|
||||
this->_domain->_do_erased_copy(x, *this, sizeof(*this));
|
||||
return x;
|
||||
}
|
||||
|
||||
/***** KEEP THESE IN SYNC WITH ERRORED_STATUS_CODE *****/
|
||||
//! Implicit copy construction from any other status code if its value type is trivially copyable and it would fit into our storage
|
||||
template <class DomainType, //
|
||||
typename std::enable_if<!detail::is_erased_status_code<status_code<DomainType>>::value //
|
||||
&& std::is_trivially_copyable<typename DomainType::value_type>::value //
|
||||
&& detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
|
||||
bool>::type = true>
|
||||
constexpr status_code(const status_code<DomainType> &v) noexcept // NOLINT
|
||||
: _base(typename _base::_value_type_constructor{}, &v.domain(), detail::erasure_cast<value_type>(v.value()))
|
||||
{
|
||||
}
|
||||
//! Implicit move construction from any other status code if its value type is trivially copyable or move relocating and it would fit into our storage
|
||||
template <class DomainType, //
|
||||
typename std::enable_if<detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value, bool>::type = true>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code(status_code<DomainType> &&v) noexcept // NOLINT
|
||||
: _base(typename _base::_value_type_constructor{}, &v.domain(), detail::erasure_cast<value_type>(v.value()))
|
||||
{
|
||||
v._domain = nullptr;
|
||||
}
|
||||
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
|
||||
template <class T, class... Args, //
|
||||
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
|
||||
typename std::enable_if<!std::is_same<typename std::decay<T>::type, status_code>::value // not copy/move of self
|
||||
&& !std::is_same<typename std::decay<T>::type, value_type>::value // not copy/move of value type
|
||||
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
|
||||
&& std::is_constructible<status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
|
||||
bool>::type = true>
|
||||
constexpr status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
|
||||
: status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
/**** By rights ought to be removed in any formal standard ****/
|
||||
//! Reset the code to empty.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 void clear() noexcept { *this = status_code(); }
|
||||
//! Return the erased `value_type` by value.
|
||||
constexpr value_type value() const noexcept { return this->_value; }
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class ErasedType> struct is_move_relocating<status_code<erased<ErasedType>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,137 +0,0 @@
|
||||
/* Pointer to a SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Sep 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_STATUS_CODE_PTR_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_CODE_PTR_HPP
|
||||
|
||||
#include "status_code.hpp"
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class StatusCode> class indirecting_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
using _base = status_code_domain;
|
||||
|
||||
public:
|
||||
using value_type = StatusCode *;
|
||||
using _base::string_ref;
|
||||
|
||||
constexpr indirecting_domain() noexcept : _base(0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id() /* unique-ish based on domain's unique id */) {}
|
||||
indirecting_domain(const indirecting_domain &) = default;
|
||||
indirecting_domain(indirecting_domain &&) = default; // NOLINT
|
||||
indirecting_domain &operator=(const indirecting_domain &) = default;
|
||||
indirecting_domain &operator=(indirecting_domain &&) = default; // NOLINT
|
||||
~indirecting_domain() = default;
|
||||
|
||||
#if __cplusplus < 201402L && !defined(_MSC_VER)
|
||||
static inline const indirecting_domain &get()
|
||||
{
|
||||
static indirecting_domain v;
|
||||
return v;
|
||||
}
|
||||
#else
|
||||
static inline constexpr const indirecting_domain &get();
|
||||
#endif
|
||||
|
||||
virtual string_ref name() const noexcept override { return typename StatusCode::domain_type().name(); } // NOLINT
|
||||
protected:
|
||||
using _mycode = status_code<indirecting_domain>;
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
return typename StatusCode::domain_type()._do_failure(*c.value());
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this);
|
||||
const auto &c1 = static_cast<const _mycode &>(code1); // NOLINT
|
||||
return typename StatusCode::domain_type()._do_equivalent(*c1.value(), code2);
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
return typename StatusCode::domain_type()._generic_code(*c.value());
|
||||
}
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
return typename StatusCode::domain_type()._do_message(*c.value());
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _mycode &>(code); // NOLINT
|
||||
typename StatusCode::domain_type()._do_throw_exception(*c.value());
|
||||
}
|
||||
#endif
|
||||
virtual void _do_erased_copy(status_code<void> &dst, const status_code<void> &src, size_t /*unused*/) const override // NOLINT
|
||||
{
|
||||
assert(dst.domain() == *this);
|
||||
assert(src.domain() == *this);
|
||||
auto &d = static_cast<_mycode &>(dst); // NOLINT
|
||||
const auto &_s = static_cast<const _mycode &>(src); // NOLINT
|
||||
const StatusCode &s = *_s.value();
|
||||
new(&d) _mycode(in_place, new StatusCode(s));
|
||||
}
|
||||
virtual void _do_erased_destroy(status_code<void> &code, size_t /*unused*/) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
auto &c = static_cast<_mycode &>(code); // NOLINT
|
||||
delete c.value(); // NOLINT
|
||||
}
|
||||
};
|
||||
#if __cplusplus >= 201402L || defined(_MSC_VER)
|
||||
template <class StatusCode> constexpr indirecting_domain<StatusCode> _indirecting_domain{};
|
||||
template <class StatusCode> inline constexpr const indirecting_domain<StatusCode> &indirecting_domain<StatusCode>::get() { return _indirecting_domain<StatusCode>; }
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
/*! Make an erased status code which indirects to a dynamically allocated status code.
|
||||
This is useful for shoehorning a rich status code with large value type into a small
|
||||
erased status code like `system_code`, with which the status code generated by this
|
||||
function is compatible. Note that this function can throw due to `bad_alloc`.
|
||||
*/
|
||||
template <class T, typename std::enable_if<is_status_code<T>::value, bool>::type = true> //
|
||||
inline status_code<erased<typename std::add_pointer<typename std::decay<T>::type>::type>> make_status_code_ptr(T &&v)
|
||||
{
|
||||
using status_code_type = typename std::decay<T>::type;
|
||||
return status_code<detail::indirecting_domain<status_code_type>>(in_place, new status_code_type(static_cast<T &&>(v)));
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,104 +0,0 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_STATUS_ERROR_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_ERROR_HPP
|
||||
|
||||
#include "status_code.hpp"
|
||||
|
||||
#include <exception> // for std::exception
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
/*! Exception type representing a thrown status_code
|
||||
*/
|
||||
template <class DomainType> class status_error;
|
||||
|
||||
/*! The erased type edition of status_error.
|
||||
*/
|
||||
template <> class status_error<void> : public std::exception
|
||||
{
|
||||
protected:
|
||||
//! Constructs an instance. Not publicly available.
|
||||
status_error() = default;
|
||||
//! Copy constructor. Not publicly available
|
||||
status_error(const status_error &) = default;
|
||||
//! Move constructor. Not publicly available
|
||||
status_error(status_error &&) = default;
|
||||
//! Copy assignment. Not publicly available
|
||||
status_error &operator=(const status_error &) = default;
|
||||
//! Move assignment. Not publicly available
|
||||
status_error &operator=(status_error &&) = default;
|
||||
//! Destructor. Not publicly available.
|
||||
~status_error() override = default;
|
||||
|
||||
public:
|
||||
//! The type of the status domain
|
||||
using domain_type = void;
|
||||
//! The type of the status code
|
||||
using status_code_type = status_code<void>;
|
||||
};
|
||||
|
||||
/*! Exception type representing a thrown status_code
|
||||
*/
|
||||
template <class DomainType> class status_error : public status_error<void>
|
||||
{
|
||||
status_code<DomainType> _code;
|
||||
typename DomainType::string_ref _msgref;
|
||||
|
||||
public:
|
||||
//! The type of the status domain
|
||||
using domain_type = DomainType;
|
||||
//! The type of the status code
|
||||
using status_code_type = status_code<DomainType>;
|
||||
|
||||
//! Constructs an instance
|
||||
explicit status_error(status_code<DomainType> code)
|
||||
: _code(static_cast<status_code<DomainType> &&>(code))
|
||||
, _msgref(_code.message())
|
||||
{
|
||||
}
|
||||
|
||||
//! Return an explanatory string
|
||||
virtual const char *what() const noexcept override { return _msgref.c_str(); } // NOLINT
|
||||
|
||||
//! Returns a reference to the code
|
||||
const status_code_type &code() const & { return _code; }
|
||||
//! Returns a reference to the code
|
||||
status_code_type &code() & { return _code; }
|
||||
//! Returns a reference to the code
|
||||
const status_code_type &&code() const && { return _code; }
|
||||
//! Returns a reference to the code
|
||||
status_code_type &&code() && { return _code; }
|
||||
};
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,184 +0,0 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Aug 2018
|
||||
|
||||
|
||||
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_SYSTEM_ERROR2_STD_ERROR_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STD_ERROR_CODE_HPP
|
||||
|
||||
#include "posix_code.hpp"
|
||||
|
||||
#if defined(_WIN32) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
#include "win32_code.hpp"
|
||||
#endif
|
||||
|
||||
#include <system_error>
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct make_std_categories
|
||||
{
|
||||
static const std::error_category &generic_category() { return std::generic_category(); }
|
||||
static const std::error_category &system_category() { return std::system_category(); }
|
||||
};
|
||||
}
|
||||
|
||||
template <class error_code_type, class make_category_types> class _error_code_domain;
|
||||
//! A wrapper of `std::error_code`.
|
||||
using std_error_code = status_code<_error_code_domain<std::error_code, detail::make_std_categories>>;
|
||||
|
||||
/*! The implementation of the domain for `std::error_code` error codes.
|
||||
*/
|
||||
template <class error_code_type, class make_categories_type> class _error_code_domain : public status_code_domain
|
||||
{
|
||||
template <class DomainType> friend class status_code;
|
||||
template <class StatusCode> friend class detail::indirecting_domain;
|
||||
using _base = status_code_domain;
|
||||
using _status_code = status_code<_error_code_domain>;
|
||||
|
||||
static _base::string_ref _make_string_ref(error_code_type c) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string msg = c.message();
|
||||
auto *p = static_cast<char *>(malloc(msg.size() + 1)); // NOLINT
|
||||
if(p == nullptr)
|
||||
{
|
||||
return _base::string_ref("failed to allocate message");
|
||||
}
|
||||
memcpy(p, msg.c_str(), msg.size() + 1);
|
||||
return _base::atomic_refcounted_string_ref(p, msg.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return _base::string_ref("failed to allocate message");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
//! The value type of the `std::error_code` code, which is the `std::error_code`
|
||||
using value_type = error_code_type;
|
||||
using _base::string_ref;
|
||||
|
||||
//! Default constructor
|
||||
constexpr explicit _error_code_domain(typename _base::unique_id_type id = 0x223a160d20de97b4) noexcept : _base(id) {}
|
||||
_error_code_domain(const _error_code_domain &) = default;
|
||||
_error_code_domain(_error_code_domain &&) = default;
|
||||
_error_code_domain &operator=(const _error_code_domain &) = default;
|
||||
_error_code_domain &operator=(_error_code_domain &&) = default;
|
||||
~_error_code_domain() = default;
|
||||
|
||||
//! Constexpr singleton getter. Returns constexpr error_code_domain variable.
|
||||
static inline constexpr const _error_code_domain &get();
|
||||
|
||||
virtual string_ref name() const noexcept override { return string_ref("error_code compatibility domain"); } // NOLINT
|
||||
protected:
|
||||
virtual bool _do_failure(const status_code<void> &code) const noexcept override final // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
return static_cast<const _status_code &>(code).value().value() != 0; // NOLINT
|
||||
}
|
||||
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override final // NOLINT
|
||||
{
|
||||
assert(code1.domain() == *this);
|
||||
const auto &c1 = static_cast<const _status_code &>(code1); // NOLINT
|
||||
const auto &cat1 = c1.value().category();
|
||||
// Are we comparing to another wrapped error_code?
|
||||
if(code2.domain() == *this)
|
||||
{
|
||||
const auto &c2 = static_cast<const _status_code &>(code2); // NOLINT
|
||||
const auto &cat2 = c2.value().category();
|
||||
// If the error code categories are identical, do literal comparison
|
||||
if(cat1 == cat2)
|
||||
{
|
||||
return c1.value().value() == c2.value().value();
|
||||
}
|
||||
// Otherwise fall back onto the _generic_code comparison, which uses default_error_condition()
|
||||
return false;
|
||||
}
|
||||
// Am I an error code with generic category?
|
||||
const auto &generic_category = make_categories_type::generic_category();
|
||||
if(cat1 == generic_category)
|
||||
{
|
||||
// Convert to generic code, and compare that
|
||||
generic_code _c1(static_cast<errc>(c1.value().value()));
|
||||
return _c1 == code2;
|
||||
}
|
||||
// Am I an error code with system category?
|
||||
const auto &system_category = make_categories_type::system_category();
|
||||
if(cat1 == system_category)
|
||||
{
|
||||
// Convert to POSIX or Win32 code, and compare that
|
||||
#ifdef _WIN32
|
||||
win32_code _c1((win32::DWORD) c1.value().value());
|
||||
#else
|
||||
posix_code _c1(c1.value().value());
|
||||
#endif
|
||||
return _c1 == code2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override final // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _status_code &>(code); // NOLINT
|
||||
// Ask my embedded error code for its mapping to std::errc, which is a subset of our generic_code errc.
|
||||
return generic_code(static_cast<errc>(c.value().default_error_condition().value()));
|
||||
}
|
||||
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _status_code &>(code); // NOLINT
|
||||
return _make_string_ref(c.value());
|
||||
}
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
|
||||
{
|
||||
assert(code.domain() == *this);
|
||||
const auto &c = static_cast<const _status_code &>(code); // NOLINT
|
||||
throw std::system_error(c.value());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
//! A constexpr source variable for the `std::error_code` code domain. Returned by `_error_code_domain<error_code_type, detail::make_std_categoriesy>::get()`.
|
||||
constexpr _error_code_domain<std::error_code, detail::make_std_categories> std_error_code_domain;
|
||||
template <class error_code_type, class make_categories_type> inline constexpr const _error_code_domain<error_code_type, make_categories_type> &_error_code_domain<error_code_type, make_categories_type>::get()
|
||||
{
|
||||
return std_error_code_domain;
|
||||
}
|
||||
// Enable implicit construction of `std_error_code` from `std::error_code`.
|
||||
inline std_error_code make_status_code(std::error_code c) noexcept
|
||||
{
|
||||
return std_error_code(in_place, c);
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A less simple result type
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (17 commits)
|
||||
File Created: Apr 2018
|
||||
|
||||
|
||||
@@ -58,57 +58,73 @@ BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
namespace trait
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Shortcut this for lower build impact
|
||||
template <class DomainType> struct _is_error_code_available<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <class DomainType> struct _is_error_code_available<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace detail
|
||||
#if 0
|
||||
template <class DomainType> struct is_error_type<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <> struct is_error_type<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <class DomainType, class Enum> struct is_error_type_enum<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>, Enum>
|
||||
{
|
||||
static constexpr bool value = boost::system::is_error_condition_enum<Enum>::value;
|
||||
};
|
||||
#endif
|
||||
} // namespace trait
|
||||
|
||||
|
||||
namespace experimental
|
||||
{
|
||||
namespace policy
|
||||
{
|
||||
template <class T, class EC, class E>
|
||||
using default_status_outcome_policy = std::conditional_t< //
|
||||
std::is_void<EC>::value && std::is_void<E>::value, //
|
||||
BOOST_OUTCOME_V2_NAMESPACE::policy::terminate, //
|
||||
std::conditional_t<(is_status_code<EC>::value || is_errored_status_code<EC>::value) && (std::is_void<E>::value || BOOST_OUTCOME_V2_NAMESPACE::trait::is_exception_ptr_available<E>::value), //
|
||||
status_code_throw<T, EC, E>, //
|
||||
BOOST_OUTCOME_V2_NAMESPACE::policy::fail_to_compile_observers //
|
||||
using default_status_outcome_policy = std::conditional_t< //
|
||||
std::is_void<EC>::value && std::is_void<E>::value, //
|
||||
BOOST_OUTCOME_V2_NAMESPACE::policy::terminate, //
|
||||
std::conditional_t<(is_status_code<EC>::value || is_errored_status_code<EC>::value) &&
|
||||
(std::is_void<E>::value || BOOST_OUTCOME_V2_NAMESPACE::trait::is_exception_ptr_available<E>::value), //
|
||||
status_code_throw<T, EC, E>, //
|
||||
BOOST_OUTCOME_V2_NAMESPACE::policy::fail_to_compile_observers //
|
||||
>>;
|
||||
} // namespace policy
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class R, class S = system_code, class P = std::exception_ptr, class NoValuePolicy = policy::default_status_outcome_policy<R, S, P>> //
|
||||
template <class R, class S = erased_errored_status_code<typename system_code::value_type>, class P = std::exception_ptr,
|
||||
class NoValuePolicy = policy::default_status_outcome_policy<R, S, P>> //
|
||||
using status_outcome = basic_outcome<R, S, P, NoValuePolicy>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class R, class S, class P, class NoValuePolicy)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_copy_constructible<R>::value &&std::is_copy_constructible<P>::value &&
|
||||
(is_status_code<S>::value || is_errored_status_code<S>::value)))
|
||||
inline basic_outcome<R, S, P, NoValuePolicy> clone(const basic_outcome<R, S, P, NoValuePolicy> &v)
|
||||
{
|
||||
if(v)
|
||||
{
|
||||
return success_type<R>(v.assume_value());
|
||||
}
|
||||
if(v.has_error() && v.has_exception())
|
||||
{
|
||||
return failure_type<S, P>(v.assume_error().clone(), v.assume_exception(), hooks::spare_storage(&v));
|
||||
}
|
||||
if(v.has_exception())
|
||||
{
|
||||
return failure_type<S, P>(in_place_type<P>, v.assume_exception(), hooks::spare_storage(&v));
|
||||
}
|
||||
return failure_type<S, P>(in_place_type<S>, v.assume_error().clone(), hooks::spare_storage(&v));
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class S, class P, class NoValuePolicy)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_copy_constructible<P>::value && (is_status_code<S>::value || is_errored_status_code<S>::value)))
|
||||
inline basic_outcome<void, S, P, NoValuePolicy> clone(const basic_outcome<void, S, P, NoValuePolicy> &v)
|
||||
{
|
||||
if(v)
|
||||
{
|
||||
return success_type<void>();
|
||||
}
|
||||
if(v.has_error() && v.has_exception())
|
||||
{
|
||||
return failure_type<S, P>(v.assume_error().clone(), v.assume_exception(), hooks::spare_storage(&v));
|
||||
}
|
||||
if(v.has_exception())
|
||||
{
|
||||
return failure_type<S, P>(in_place_type<P>, v.assume_exception(), hooks::spare_storage(&v));
|
||||
}
|
||||
return failure_type<S, P>(in_place_type<S>, v.assume_error().clone(), hooks::spare_storage(&v));
|
||||
}
|
||||
|
||||
namespace policy
|
||||
{
|
||||
template <class T, class DomainType, class E> struct status_code_throw<T, status_code<DomainType>, E> : base
|
||||
@@ -120,7 +136,8 @@ SIGNATURE NOT RECOGNISED
|
||||
{
|
||||
if(base::_has_exception(static_cast<Impl &&>(self)))
|
||||
{
|
||||
BOOST_OUTCOME_V2_NAMESPACE::policy::detail::_rethrow_exception<trait::is_exception_ptr_available<E>::value>(base::_exception<T, status_code<DomainType>, E, status_code_throw>(static_cast<Impl &&>(self))); // NOLINT
|
||||
BOOST_OUTCOME_V2_NAMESPACE::policy::detail::_rethrow_exception<trait::is_exception_ptr_available<E>::value>(
|
||||
base::_exception<T, status_code<DomainType>, E, status_code_throw>(static_cast<Impl &&>(self))); // NOLINT
|
||||
}
|
||||
if(base::_has_error(static_cast<Impl &&>(self)))
|
||||
{
|
||||
@@ -135,7 +152,8 @@ SIGNATURE NOT RECOGNISED
|
||||
template <class Impl> static constexpr void wide_error_check(Impl &&self) { _base::narrow_error_check(static_cast<Impl &&>(self)); }
|
||||
template <class Impl> static constexpr void wide_exception_check(Impl &&self) { _base::narrow_exception_check(static_cast<Impl &&>(self)); }
|
||||
};
|
||||
template <class T, class DomainType, class E> struct status_code_throw<T, errored_status_code<DomainType>, E> : status_code_throw<T, status_code<DomainType>, E>
|
||||
template <class T, class DomainType, class E>
|
||||
struct status_code_throw<T, errored_status_code<DomainType>, E> : status_code_throw<T, status_code<DomainType>, E>
|
||||
{
|
||||
status_code_throw() = default;
|
||||
using status_code_throw<T, status_code<DomainType>, E>::status_code_throw;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A very simple result type
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
|
||||
File Created: Apr 2018
|
||||
|
||||
|
||||
@@ -34,31 +34,97 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include "../basic_result.hpp"
|
||||
#include "../policy/fail_to_compile_observers.hpp"
|
||||
|
||||
#include "status-code/system_error2.hpp"
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_USE_STD_ADDRESSOF
|
||||
#if BOOST_OUTCOME_USE_STD_ADDRESSOF
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_USE_STD_ADDRESSOF 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __PCPP_ALWAYS_TRUE__
|
||||
#include "status-code/status-code/system_error2.hpp"
|
||||
#elif !BOOST_OUTCOME_USE_SYSTEM_STATUS_CODE && __has_include("status-code/status-code/system_error2.hpp")
|
||||
#include "status-code/status-code/system_error2.hpp"
|
||||
#else
|
||||
#include <status-code/system_error2.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
namespace trait
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Shortcut this for lower build impact. Used to tell outcome's converting constructors
|
||||
// that they can do E => EC or E => EP as necessary.
|
||||
template <class DomainType> struct _is_error_code_available<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
using type = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>;
|
||||
};
|
||||
template <class DomainType> struct _is_error_code_available<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
using type = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>;
|
||||
};
|
||||
} // namespace detail
|
||||
#if 0 // Do NOT enable weakened implicit construction for these types
|
||||
template <class DomainType> struct is_error_type<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <> struct is_error_type<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <class DomainType, class Enum> struct is_error_type_enum<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>, Enum>
|
||||
{
|
||||
static constexpr bool value = boost::system::is_error_condition_enum<Enum>::value;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class DomainType> struct is_move_bitcopying<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::traits::is_move_bitcopying<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>::value;
|
||||
};
|
||||
template <class DomainType> struct is_move_bitcopying<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::traits::is_move_bitcopying<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>>::value;
|
||||
};
|
||||
} // namespace trait
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Customise _set_error_is_errno
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::generic_code & /*unused*/) { state._status |= status_error_is_errno; }
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::posix_code & /*unused*/) { state._status |= status_error_is_errno; }
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc & /*unused*/) { state._status |= status_error_is_errno; }
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::generic_code & /*unused*/)
|
||||
{
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::posix_code & /*unused*/)
|
||||
{
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
#endif
|
||||
template <class State> constexpr inline void _set_error_is_errno(State &state, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::errc & /*unused*/)
|
||||
{
|
||||
state._status.set_have_error_is_errno(true);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace experimental
|
||||
{
|
||||
using namespace BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE;
|
||||
using BOOST_OUTCOME_V2_NAMESPACE::success;
|
||||
using BOOST_OUTCOME_V2_NAMESPACE::failure;
|
||||
using BOOST_OUTCOME_V2_NAMESPACE::success;
|
||||
|
||||
namespace policy
|
||||
{
|
||||
using namespace BOOST_OUTCOME_V2_NAMESPACE::policy;
|
||||
template <class T, class EC, class E> struct status_code_throw
|
||||
{
|
||||
static_assert(!std::is_same<T, T>::value, "policy::status_code_throw not specialised for these types, did you use status_result<T, status_code<DomainType>, E>?");
|
||||
static_assert(!std::is_same<T, T>::value,
|
||||
"policy::status_code_throw not specialised for these types, did you use status_result<T, status_code<DomainType>, E>?");
|
||||
};
|
||||
template <class T, class DomainType> struct status_code_throw<T, status_code<DomainType>, void> : base
|
||||
{
|
||||
@@ -79,7 +145,8 @@ namespace experimental
|
||||
}
|
||||
template <class Impl> static constexpr void wide_error_check(Impl &&self) { _base::narrow_error_check(static_cast<Impl &&>(self)); }
|
||||
};
|
||||
template <class T, class DomainType> struct status_code_throw<T, errored_status_code<DomainType>, void> : status_code_throw<T, status_code<DomainType>, void>
|
||||
template <class T, class DomainType>
|
||||
struct status_code_throw<T, errored_status_code<DomainType>, void> : status_code_throw<T, status_code<DomainType>, void>
|
||||
{
|
||||
status_code_throw() = default;
|
||||
using status_code_throw<T, status_code<DomainType>, void>::status_code_throw;
|
||||
@@ -95,12 +162,41 @@ namespace experimental
|
||||
>>;
|
||||
} // namespace policy
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class R, class S = system_code, class NoValuePolicy = policy::default_status_result_policy<R, S>> //
|
||||
template <class R, class S = erased_errored_status_code<typename system_code::value_type>,
|
||||
class NoValuePolicy = policy::default_status_result_policy<R, S>> //
|
||||
using status_result = basic_result<R, S, NoValuePolicy>;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class R, class S, class NoValuePolicy)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_copy_constructible<R>::value && (is_status_code<S>::value || is_errored_status_code<S>::value)))
|
||||
inline basic_result<R, S, NoValuePolicy> clone(const basic_result<R, S, NoValuePolicy> &v)
|
||||
{
|
||||
if(v)
|
||||
{
|
||||
return success_type<R>(v.assume_value());
|
||||
}
|
||||
return failure_type<S>(v.assume_error().clone(), hooks::spare_storage(&v));
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class S, class NoValuePolicy)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(is_status_code<S>::value || is_errored_status_code<S>::value))
|
||||
inline basic_result<void, S, NoValuePolicy> clone(const basic_result<void, S, NoValuePolicy> &v)
|
||||
{
|
||||
if(v)
|
||||
{
|
||||
return success_type<void>();
|
||||
}
|
||||
return failure_type<S>(v.assume_error().clone(), hooks::spare_storage(&v));
|
||||
}
|
||||
|
||||
} // namespace experimental
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* iostream specialisations for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (21 commits)
|
||||
File Created: July 2017
|
||||
|
||||
|
||||
@@ -42,57 +42,96 @@ namespace detail
|
||||
{
|
||||
template <class T> typename std::add_lvalue_reference<T>::type lvalueref() noexcept;
|
||||
|
||||
template <class T> inline std::ostream &operator<<(std::ostream &s, const value_storage_trivial<T> &v)
|
||||
template <template <class, class> class ValueStorage, class T, class E> inline std::ostream &value_storage_out(std::ostream &s, const ValueStorage<T, E> &v)
|
||||
{
|
||||
s << v._status << " ";
|
||||
if((v._status & status_have_value) != 0)
|
||||
s << static_cast<uint16_t>(v._status.status_value) << " " << v._status.spare_storage_value << " ";
|
||||
if(v._status.have_value())
|
||||
{
|
||||
s << v._value; // NOLINT
|
||||
}
|
||||
if(v._status.have_error())
|
||||
{
|
||||
s << v._error; // NOLINT
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template <template <class, class> class ValueStorage, class E> inline std::ostream &value_storage_out(std::ostream &s, const ValueStorage<void, E> &v)
|
||||
{
|
||||
s << static_cast<uint16_t>(v._status.status_value) << " " << v._status.spare_storage_value << " ";
|
||||
if(v._status.have_error())
|
||||
{
|
||||
s << v._error; // NOLINT
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template <template <class, class> class ValueStorage, class T> inline std::ostream &value_storage_out(std::ostream &s, const ValueStorage<T, void> &v)
|
||||
{
|
||||
s << static_cast<uint16_t>(v._status.status_value) << " " << v._status.spare_storage_value << " ";
|
||||
if(v._status.have_value())
|
||||
{
|
||||
s << v._value; // NOLINT
|
||||
}
|
||||
return s;
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &s, const value_storage_trivial<void> &v)
|
||||
|
||||
template <class T, class E> inline std::ostream &operator<<(std::ostream &s, const value_storage_trivial<T, E> &v) { return value_storage_out(s, v); }
|
||||
template <class T, class E> inline std::ostream &operator<<(std::ostream &s, const value_storage_nontrivial<T, E> &v) { return value_storage_out(s, v); }
|
||||
|
||||
template <template <class, class> class ValueStorage, class T, class E> inline std::istream &value_storage_in(std::istream &s, ValueStorage<T, E> &v)
|
||||
{
|
||||
s << v._status << " ";
|
||||
return s;
|
||||
}
|
||||
template <class T> inline std::ostream &operator<<(std::ostream &s, const value_storage_nontrivial<T> &v)
|
||||
{
|
||||
s << v._status << " ";
|
||||
if((v._status & status_have_value) != 0)
|
||||
using type = ValueStorage<T, E>;
|
||||
v.~type();
|
||||
new(&v) type;
|
||||
uint16_t x, y;
|
||||
s >> x >> y;
|
||||
v._status.status_value = static_cast<detail::status>(x);
|
||||
v._status.spare_storage_value = y;
|
||||
if(v._status.have_value())
|
||||
{
|
||||
s << v._value; // NOLINT
|
||||
new(BOOST_OUTCOME_ADDRESS_OF(v._value)) decltype(v._value)(); // NOLINT
|
||||
s >> v._value; // NOLINT
|
||||
}
|
||||
if(v._status.have_error())
|
||||
{
|
||||
new(BOOST_OUTCOME_ADDRESS_OF(v._error)) decltype(v._error)(); // NOLINT
|
||||
s >> v._error; // NOLINT
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template <class T> inline std::istream &operator>>(std::istream &s, value_storage_trivial<T> &v)
|
||||
template <template <class, class> class ValueStorage, class E> inline std::istream &value_storage_in(std::istream &s, ValueStorage<void, E> &v)
|
||||
{
|
||||
v = value_storage_trivial<T>();
|
||||
s >> v._status;
|
||||
if((v._status & status_have_value) != 0)
|
||||
using type = ValueStorage<void, E>;
|
||||
v.~type();
|
||||
new(&v) type;
|
||||
uint16_t x, y;
|
||||
s >> x >> y;
|
||||
v._status.status_value = static_cast<detail::status>(x);
|
||||
v._status.spare_storage_value = y;
|
||||
if(v._status.have_error())
|
||||
{
|
||||
new(&v._value) decltype(v._value)(); // NOLINT
|
||||
s >> v._value; // NOLINT
|
||||
new(BOOST_OUTCOME_ADDRESS_OF(v._error)) decltype(v._error)(); // NOLINT
|
||||
s >> v._error; // NOLINT
|
||||
}
|
||||
return s;
|
||||
}
|
||||
inline std::istream &operator>>(std::istream &s, value_storage_trivial<devoid<void>> &v)
|
||||
template <template <class, class> class ValueStorage, class T> inline std::istream &value_storage_in(std::istream &s, ValueStorage<T, void> &v)
|
||||
{
|
||||
v = value_storage_trivial<devoid<void>>();
|
||||
s >> v._status;
|
||||
return s;
|
||||
}
|
||||
template <class T> inline std::istream &operator>>(std::istream &s, value_storage_nontrivial<T> &v)
|
||||
{
|
||||
v = value_storage_nontrivial<T>();
|
||||
s >> v._status;
|
||||
if((v._status & status_have_value) != 0)
|
||||
using type = ValueStorage<T, void>;
|
||||
v.~type();
|
||||
new(&v) type;
|
||||
uint16_t x, y;
|
||||
s >> x >> y;
|
||||
v._status.status_value = static_cast<detail::status>(x);
|
||||
v._status.spare_storage_value = y;
|
||||
if(v._status.have_value())
|
||||
{
|
||||
new(&v._value) decltype(v._value)(); // NOLINT
|
||||
s >> v._value; // NOLINT
|
||||
new(BOOST_OUTCOME_ADDRESS_OF(v._value)) decltype(v._value)(); // NOLINT
|
||||
s >> v._value; // NOLINT
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template <class T, class E> inline std::istream &operator>>(std::istream &s, value_storage_trivial<T, E> &v) { return value_storage_in(s, v); }
|
||||
template <class T, class E> inline std::istream &operator>>(std::istream &s, value_storage_nontrivial<T, E> &v) { return value_storage_in(s, v); }
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_constructible<std::error_code, T>::value))
|
||||
inline std::string safe_message(T && /*unused*/) { return {}; }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A less simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (1 commit)
|
||||
File Created: June 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (13 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (6 commits) and Andrzej Krzemieński <akrzemi1@gmail.com> (1 commit)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
@@ -31,72 +31,192 @@ DEALINGS IN THE SOFTWARE.
|
||||
#ifndef BOOST_OUTCOME_POLICY_BASE_HPP
|
||||
#define BOOST_OUTCOME_POLICY_BASE_HPP
|
||||
|
||||
#include "../config.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include "../detail/value_storage.hpp"
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
namespace hooks
|
||||
{
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_result_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_result_copy_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_result_move_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U, class... Args>
|
||||
constexpr inline void hook_result_in_place_construction(T * /*unused*/, in_place_type_t<U> /*unused*/, Args &&... /*unused*/) noexcept
|
||||
{
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class... U> constexpr inline void hook_outcome_construction(T * /*unused*/, U &&... /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_outcome_copy_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U> constexpr inline void hook_outcome_move_construction(T * /*unused*/, U && /*unused*/) noexcept {}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class U, class... Args>
|
||||
constexpr inline void hook_outcome_in_place_construction(T * /*unused*/, in_place_type_t<U> /*unused*/, Args &&... /*unused*/) noexcept
|
||||
{
|
||||
}
|
||||
} // namespace hooks
|
||||
#endif
|
||||
|
||||
namespace policy
|
||||
{
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
namespace detail
|
||||
{
|
||||
using BOOST_OUTCOME_V2_NAMESPACE::detail::make_ub;
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
struct base
|
||||
{
|
||||
template <class... Args> static constexpr void _silence_unused(Args &&... /*unused*/) noexcept {}
|
||||
protected:
|
||||
template <class Impl>
|
||||
static constexpr
|
||||
#ifdef _MSC_VER
|
||||
__declspec(noreturn)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
__attribute__((noreturn))
|
||||
#endif
|
||||
void _ub(Impl && /*unused*/)
|
||||
{
|
||||
assert(false); // NOLINT
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
__builtin_unreachable();
|
||||
#elif defined(_MSC_VER)
|
||||
__assume(0);
|
||||
#endif
|
||||
}
|
||||
template <class Impl> static constexpr void _make_ub(Impl &&self) noexcept { return detail::make_ub(static_cast<Impl &&>(self)); }
|
||||
template <class Impl> static constexpr bool _has_value(Impl &&self) noexcept { return self._state._status.have_value(); }
|
||||
template <class Impl> static constexpr bool _has_error(Impl &&self) noexcept { return self._state._status.have_error(); }
|
||||
template <class Impl> static constexpr bool _has_exception(Impl &&self) noexcept { return self._state._status.have_exception(); }
|
||||
template <class Impl> static constexpr bool _has_error_is_errno(Impl &&self) noexcept { return self._state._status.have_error_is_errno(); }
|
||||
|
||||
template <class Impl> static constexpr bool _has_value(Impl &&self) noexcept { return (self._state._status & BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_value) != 0; }
|
||||
template <class Impl> static constexpr bool _has_error(Impl &&self) noexcept { return (self._state._status & BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_error) != 0; }
|
||||
template <class Impl> static constexpr bool _has_exception(Impl &&self) noexcept { return (self._state._status & BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_exception) != 0; }
|
||||
template <class Impl> static constexpr bool _has_error_is_errno(Impl &&self) noexcept { return (self._state._status & BOOST_OUTCOME_V2_NAMESPACE::detail::status_error_is_errno) != 0; }
|
||||
|
||||
template <class Impl> static constexpr void _set_has_value(Impl &&self, bool v) noexcept { v ? self._state._status |= BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_value : self._state._status &= ~BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_value; }
|
||||
template <class Impl> static constexpr void _set_has_error(Impl &&self, bool v) noexcept { v ? self._state._status |= BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_error : self._state._status &= ~BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_error; }
|
||||
template <class Impl> static constexpr void _set_has_exception(Impl &&self, bool v) noexcept { v ? self._state._status |= BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_exception : self._state._status &= ~BOOST_OUTCOME_V2_NAMESPACE::detail::status_have_exception; }
|
||||
template <class Impl> static constexpr void _set_has_error_is_errno(Impl &&self, bool v) noexcept { v ? self._state._status |= BOOST_OUTCOME_V2_NAMESPACE::detail::status_error_is_errno : self._state._status &= ~BOOST_OUTCOME_V2_NAMESPACE::detail::status_error_is_errno; }
|
||||
template <class Impl> static constexpr void _set_has_value(Impl &&self, bool v) noexcept { self._state._status.set_have_value(v); }
|
||||
template <class Impl> static constexpr void _set_has_error(Impl &&self, bool v) noexcept { self._state._status.set_have_error(v); }
|
||||
template <class Impl> static constexpr void _set_has_exception(Impl &&self, bool v) noexcept { self._state._status.set_have_exception(v); }
|
||||
template <class Impl> static constexpr void _set_has_error_is_errno(Impl &&self, bool v) noexcept { self._state._status.set_have_error_is_errno(v); }
|
||||
|
||||
template <class Impl> static constexpr auto &&_value(Impl &&self) noexcept { return static_cast<Impl &&>(self)._state._value; }
|
||||
template <class Impl> static constexpr auto &&_error(Impl &&self) noexcept { return static_cast<Impl &&>(self)._error; }
|
||||
template <class Impl> static constexpr auto &&_error(Impl &&self) noexcept { return static_cast<Impl &&>(self)._state._error; }
|
||||
|
||||
public:
|
||||
template <class R, class S, class P, class NoValuePolicy, class Impl> static inline constexpr auto &&_exception(Impl &&self) noexcept;
|
||||
|
||||
template <class T, class U> static constexpr inline void on_result_construction(T *inst, U &&v) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_result_construction(inst, static_cast<U &&>(v));
|
||||
#else
|
||||
(void) inst;
|
||||
(void) v;
|
||||
#endif
|
||||
}
|
||||
template <class T, class U> static constexpr inline void on_result_copy_construction(T *inst, U &&v) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_result_copy_construction(inst, static_cast<U &&>(v));
|
||||
#else
|
||||
(void) inst;
|
||||
(void) v;
|
||||
#endif
|
||||
}
|
||||
template <class T, class U> static constexpr inline void on_result_move_construction(T *inst, U &&v) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_result_move_construction(inst, static_cast<U &&>(v));
|
||||
#else
|
||||
(void) inst;
|
||||
(void) v;
|
||||
#endif
|
||||
}
|
||||
template <class T, class U, class... Args>
|
||||
static constexpr inline void on_result_in_place_construction(T *inst, in_place_type_t<U> _, Args &&... args) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_result_in_place_construction(inst, _, static_cast<Args &&>(args)...);
|
||||
#else
|
||||
(void) inst;
|
||||
(void) _;
|
||||
_silence_unused(static_cast<Args &&>(args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class... U> static constexpr inline void on_outcome_construction(T *inst, U &&... args) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_outcome_construction(inst, static_cast<U &&>(args)...);
|
||||
#else
|
||||
(void) inst;
|
||||
_silence_unused(static_cast<U &&>(args)...);
|
||||
#endif
|
||||
}
|
||||
template <class T, class U> static constexpr inline void on_outcome_copy_construction(T *inst, U &&v) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_outcome_copy_construction(inst, static_cast<U &&>(v));
|
||||
#else
|
||||
(void) inst;
|
||||
(void) v;
|
||||
#endif
|
||||
}
|
||||
template <class T, class U> static constexpr inline void on_outcome_move_construction(T *inst, U &&v) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_outcome_move_construction(inst, static_cast<U &&>(v));
|
||||
#else
|
||||
(void) inst;
|
||||
(void) v;
|
||||
#endif
|
||||
}
|
||||
template <class T, class U, class... Args>
|
||||
static constexpr inline void on_outcome_in_place_construction(T *inst, in_place_type_t<U> _, Args &&... args) noexcept
|
||||
{
|
||||
#if BOOST_OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
|
||||
using namespace hooks;
|
||||
hook_outcome_in_place_construction(inst, _, static_cast<Args &&>(args)...);
|
||||
#else
|
||||
(void) inst;
|
||||
(void) _;
|
||||
_silence_unused(static_cast<Args &&>(args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Impl> static constexpr void narrow_value_check(Impl &&self) noexcept
|
||||
{
|
||||
if(!_has_value(self))
|
||||
{
|
||||
_ub(self);
|
||||
_make_ub(self);
|
||||
}
|
||||
}
|
||||
template <class Impl> static constexpr void narrow_error_check(Impl &&self) noexcept
|
||||
{
|
||||
if(!_has_error(self))
|
||||
{
|
||||
_ub(self);
|
||||
_make_ub(self);
|
||||
}
|
||||
}
|
||||
template <class Impl> static constexpr void narrow_exception_check(Impl &&self) noexcept
|
||||
{
|
||||
if(!_has_exception(self))
|
||||
{
|
||||
_ub(self);
|
||||
_make_ub(self);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
|
||||
File Created: Sep 2018
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (10 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Policies for result and outcome
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (13 commits)
|
||||
File Created: Oct 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A very simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
|
||||
File Created: June 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
|
||||
#define BOOST_OUTCOME_PREVIOUS_COMMIT_REF b93403b9a55355b8f6783320c8d2db2c14b3517d
|
||||
#define BOOST_OUTCOME_PREVIOUS_COMMIT_DATE "2019-02-28 22:02:20 +00:00"
|
||||
#define BOOST_OUTCOME_PREVIOUS_COMMIT_UNIQUE b93403b9
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A less simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
|
||||
File Created: June 2017
|
||||
|
||||
|
||||
@@ -34,10 +34,13 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include "basic_outcome.hpp"
|
||||
#include "std_result.hpp"
|
||||
|
||||
#ifndef STD_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
|
||||
#define STD_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
|
||||
namespace std // NOLINT
|
||||
{
|
||||
inline exception_ptr basic_outcome_failure_exception_from_error(const error_code &ec) { return make_exception_ptr(system_error(ec)); }
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* A very simple result type
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
|
||||
File Created: June 2017
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Type sugar for success and failure
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (25 commits)
|
||||
File Created: July 2017
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ template <class T> struct BOOST_OUTCOME_NODISCARD success_type
|
||||
|
||||
private:
|
||||
value_type _value;
|
||||
uint16_t _spare_storage{0};
|
||||
|
||||
public:
|
||||
success_type() = default;
|
||||
@@ -54,8 +55,9 @@ public:
|
||||
~success_type() = default;
|
||||
BOOST_OUTCOME_TEMPLATE(class U)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_same<success_type, std::decay_t<U>>::value))
|
||||
constexpr explicit success_type(U &&v)
|
||||
constexpr explicit success_type(U &&v, uint16_t spare_storage = 0)
|
||||
: _value(static_cast<U &&>(v)) // NOLINT
|
||||
, _spare_storage(spare_storage)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -63,10 +65,14 @@ public:
|
||||
constexpr const value_type &value() const & { return _value; }
|
||||
constexpr value_type &&value() && { return static_cast<value_type &&>(_value); }
|
||||
constexpr const value_type &&value() const && { return static_cast<value_type &&>(_value); }
|
||||
|
||||
constexpr uint16_t spare_storage() const { return _spare_storage; }
|
||||
};
|
||||
template <> struct BOOST_OUTCOME_NODISCARD success_type<void>
|
||||
{
|
||||
using value_type = void;
|
||||
|
||||
constexpr uint16_t spare_storage() const { return 0; }
|
||||
};
|
||||
/*! Returns type sugar for implicitly constructing a `basic_result<T>` with a successful state,
|
||||
default constructing `T` if necessary.
|
||||
@@ -76,11 +82,22 @@ inline constexpr success_type<void> success() noexcept
|
||||
return success_type<void>{};
|
||||
}
|
||||
/*! Returns type sugar for implicitly constructing a `basic_result<T>` with a successful state.
|
||||
\effects Copies or moves the successful state supplied into the returned type sugar.
|
||||
\effects Copies the successful state supplied into the returned type sugar.
|
||||
*/
|
||||
template <class T> inline constexpr success_type<std::decay_t<T>> success(T &&v)
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_copy_constructible<T>::value))
|
||||
inline constexpr success_type<std::decay_t<T>> success(const T &v, uint16_t spare_storage = 0)
|
||||
{
|
||||
return success_type<std::decay_t<T>>{static_cast<T &&>(v)};
|
||||
return success_type<std::decay_t<T>>{v, spare_storage};
|
||||
}
|
||||
/*! Returns type sugar for implicitly constructing a `basic_result<T>` with a successful state.
|
||||
\effects Moves the successful state supplied into the returned type sugar.
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<T>::value))
|
||||
inline constexpr success_type<std::decay_t<T>> success(T &&v, uint16_t spare_storage = 0)
|
||||
{
|
||||
return success_type<std::decay_t<T>>{static_cast<T &&>(v), spare_storage};
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
@@ -92,9 +109,10 @@ template <class EC, class E = void> struct BOOST_OUTCOME_NODISCARD failure_type
|
||||
using exception_type = E;
|
||||
|
||||
private:
|
||||
bool _have_error{}, _have_exception{};
|
||||
error_type _error;
|
||||
exception_type _exception;
|
||||
bool _have_error{false}, _have_exception{false};
|
||||
uint16_t _spare_storage{0};
|
||||
|
||||
struct error_init_tag
|
||||
{
|
||||
@@ -111,25 +129,29 @@ public:
|
||||
failure_type &operator=(failure_type &&) = default; // NOLINT
|
||||
~failure_type() = default;
|
||||
template <class U, class V>
|
||||
constexpr explicit failure_type(U &&u, V &&v)
|
||||
: _have_error(true)
|
||||
, _have_exception(true)
|
||||
, _error(static_cast<U &&>(u))
|
||||
constexpr explicit failure_type(U &&u, V &&v, uint16_t spare_storage = 0)
|
||||
: _error(static_cast<U &&>(u))
|
||||
, _exception(static_cast<V &&>(v))
|
||||
, _have_error(true)
|
||||
, _have_exception(true)
|
||||
, _spare_storage(spare_storage)
|
||||
{
|
||||
}
|
||||
template <class U>
|
||||
constexpr explicit failure_type(in_place_type_t<error_type> /*unused*/, U &&u, error_init_tag /*unused*/ = error_init_tag())
|
||||
: _have_error(true)
|
||||
, _error(static_cast<U &&>(u))
|
||||
constexpr explicit failure_type(in_place_type_t<error_type> /*unused*/, U &&u, uint16_t spare_storage = 0, error_init_tag /*unused*/ = error_init_tag())
|
||||
: _error(static_cast<U &&>(u))
|
||||
, _exception()
|
||||
, _have_error(true)
|
||||
, _spare_storage(spare_storage)
|
||||
{
|
||||
}
|
||||
template <class U>
|
||||
constexpr explicit failure_type(in_place_type_t<exception_type> /*unused*/, U &&u, exception_init_tag /*unused*/ = exception_init_tag())
|
||||
: _have_exception(true)
|
||||
, _error()
|
||||
constexpr explicit failure_type(in_place_type_t<exception_type> /*unused*/, U &&u, uint16_t spare_storage = 0,
|
||||
exception_init_tag /*unused*/ = exception_init_tag())
|
||||
: _error()
|
||||
, _exception(static_cast<U &&>(u))
|
||||
, _have_exception(true)
|
||||
, _spare_storage(spare_storage)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -145,6 +167,8 @@ public:
|
||||
constexpr const exception_type &exception() const & { return _exception; }
|
||||
constexpr exception_type &&exception() && { return static_cast<exception_type &&>(_exception); }
|
||||
constexpr const exception_type &&exception() const && { return static_cast<exception_type &&>(_exception); }
|
||||
|
||||
constexpr uint16_t spare_storage() const { return _spare_storage; }
|
||||
};
|
||||
template <class EC> struct BOOST_OUTCOME_NODISCARD failure_type<EC, void>
|
||||
{
|
||||
@@ -153,6 +177,7 @@ template <class EC> struct BOOST_OUTCOME_NODISCARD failure_type<EC, void>
|
||||
|
||||
private:
|
||||
error_type _error;
|
||||
uint16_t _spare_storage{0};
|
||||
|
||||
public:
|
||||
failure_type() = default;
|
||||
@@ -163,8 +188,9 @@ public:
|
||||
~failure_type() = default;
|
||||
BOOST_OUTCOME_TEMPLATE(class U)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_same<failure_type, std::decay_t<U>>::value))
|
||||
constexpr explicit failure_type(U &&u)
|
||||
constexpr explicit failure_type(U &&u, uint16_t spare_storage = 0)
|
||||
: _error(static_cast<U &&>(u)) // NOLINT
|
||||
, _spare_storage(spare_storage)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -172,6 +198,8 @@ public:
|
||||
constexpr const error_type &error() const & { return _error; }
|
||||
constexpr error_type &&error() && { return static_cast<error_type &&>(_error); }
|
||||
constexpr const error_type &&error() const && { return static_cast<error_type &&>(_error); }
|
||||
|
||||
constexpr uint16_t spare_storage() const { return _spare_storage; }
|
||||
};
|
||||
template <class E> struct BOOST_OUTCOME_NODISCARD failure_type<void, E>
|
||||
{
|
||||
@@ -180,6 +208,7 @@ template <class E> struct BOOST_OUTCOME_NODISCARD failure_type<void, E>
|
||||
|
||||
private:
|
||||
exception_type _exception;
|
||||
uint16_t _spare_storage{0};
|
||||
|
||||
public:
|
||||
failure_type() = default;
|
||||
@@ -190,8 +219,9 @@ public:
|
||||
~failure_type() = default;
|
||||
BOOST_OUTCOME_TEMPLATE(class V)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_same<failure_type, std::decay_t<V>>::value))
|
||||
constexpr explicit failure_type(V &&v)
|
||||
constexpr explicit failure_type(V &&v, uint16_t spare_storage = 0)
|
||||
: _exception(static_cast<V &&>(v)) // NOLINT
|
||||
, _spare_storage(spare_storage)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -199,20 +229,62 @@ public:
|
||||
constexpr const exception_type &exception() const & { return _exception; }
|
||||
constexpr exception_type &&exception() && { return static_cast<exception_type &&>(_exception); }
|
||||
constexpr const exception_type &&exception() const && { return static_cast<exception_type &&>(_exception); }
|
||||
|
||||
constexpr uint16_t spare_storage() const { return _spare_storage; }
|
||||
};
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class EC> inline constexpr failure_type<std::decay_t<EC>> failure(EC &&v)
|
||||
BOOST_OUTCOME_TEMPLATE(class EC)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_copy_constructible<EC>::value))
|
||||
inline constexpr failure_type<std::decay_t<EC>> failure(const EC &v, uint16_t spare_storage = 0)
|
||||
{
|
||||
return failure_type<std::decay_t<EC>>{static_cast<EC &&>(v)};
|
||||
return failure_type<std::decay_t<EC>>{v, spare_storage};
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class EC, class E> inline constexpr failure_type<std::decay_t<EC>, std::decay_t<E>> failure(EC &&v, E &&w)
|
||||
BOOST_OUTCOME_TEMPLATE(class EC)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<EC>::value))
|
||||
inline constexpr failure_type<std::decay_t<EC>> failure(EC &&v, uint16_t spare_storage = 0)
|
||||
{
|
||||
return failure_type<std::decay_t<EC>, std::decay_t<E>>{static_cast<EC &&>(v), static_cast<E &&>(w)};
|
||||
return failure_type<std::decay_t<EC>>{static_cast<EC &&>(v), spare_storage};
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class EC, class E)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_copy_constructible<EC>::value &&std::is_copy_constructible<E>::value))
|
||||
inline constexpr failure_type<std::decay_t<EC>, std::decay_t<E>> failure(const EC &v, const E &w, uint16_t spare_storage = 0)
|
||||
{
|
||||
return failure_type<std::decay_t<EC>, std::decay_t<E>>{v, w, spare_storage};
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class EC, class E)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_copy_constructible<EC>::value &&std::is_move_constructible<E>::value))
|
||||
inline constexpr failure_type<std::decay_t<EC>, std::decay_t<E>> failure(const EC &v, E &&w, uint16_t spare_storage = 0)
|
||||
{
|
||||
return failure_type<std::decay_t<EC>, std::decay_t<E>>{v, static_cast<E &&>(w), spare_storage};
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class EC, class E)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<EC>::value &&std::is_copy_constructible<E>::value))
|
||||
inline constexpr failure_type<std::decay_t<EC>, std::decay_t<E>> failure(EC &&v, const E &w, uint16_t spare_storage = 0)
|
||||
{
|
||||
return failure_type<std::decay_t<EC>, std::decay_t<E>>{static_cast<EC &&>(v), w, spare_storage};
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class EC, class E)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<EC>::value &&std::is_move_constructible<E>::value))
|
||||
inline constexpr failure_type<std::decay_t<EC>, std::decay_t<E>> failure(EC &&v, E &&w, uint16_t spare_storage = 0)
|
||||
{
|
||||
return failure_type<std::decay_t<EC>, std::decay_t<E>>{static_cast<EC &&>(v), static_cast<E &&>(w), spare_storage};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Traits for Outcome
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2018-2023 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
|
||||
File Created: March 2018
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
|
||||
|
||||
namespace trait
|
||||
{
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class R> //
|
||||
@@ -49,9 +49,17 @@ SIGNATURE NOT RECOGNISED
|
||||
&& !std::is_array<R>::value //
|
||||
&& (std::is_void<R>::value || (std::is_object<R>::value //
|
||||
&& std::is_destructible<R>::value)) //
|
||||
);
|
||||
);
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type definition is_error_type. Potential doc page: NOT FOUND
|
||||
*/
|
||||
template <class T> struct is_move_bitcopying
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type definition is_error_type. Potential doc page: NOT FOUND
|
||||
*/
|
||||
template <class E> struct is_error_type
|
||||
@@ -59,7 +67,7 @@ type definition is_error_type. Potential doc page: NOT FOUND
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type definition is_error_type_enum. Potential doc page: NOT FOUND
|
||||
*/
|
||||
template <class E, class Enum> struct is_error_type_enum
|
||||
@@ -98,30 +106,34 @@ type definition is_error_type_enum. Potential doc page: NOT FOUND
|
||||
template <class T> struct _is_error_code_available
|
||||
{
|
||||
static constexpr bool value = detail::introspect_make_error_code<T>::value;
|
||||
using type = typename detail::introspect_make_error_code<T>::type;
|
||||
};
|
||||
template <class T> struct _is_exception_ptr_available
|
||||
{
|
||||
static constexpr bool value = detail::introspect_make_exception_ptr<T>::value;
|
||||
using type = typename detail::introspect_make_exception_ptr<T>::type;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type definition is_error_code_available. Potential doc page: NOT FOUND
|
||||
*/
|
||||
template <class T> struct is_error_code_available
|
||||
{
|
||||
static constexpr bool value = detail::_is_error_code_available<std::decay_t<T>>::value;
|
||||
using type = typename detail::_is_error_code_available<std::decay_t<T>>::type;
|
||||
};
|
||||
template <class T> constexpr bool is_error_code_available_v = detail::_is_error_code_available<std::decay_t<T>>::value;
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
type definition is_exception_ptr_available. Potential doc page: NOT FOUND
|
||||
*/
|
||||
template <class T> struct is_exception_ptr_available
|
||||
{
|
||||
static constexpr bool value = detail::_is_exception_ptr_available<std::decay<T>>::value;
|
||||
static constexpr bool value = detail::_is_exception_ptr_available<std::decay_t<T>>::value;
|
||||
using type = typename detail::_is_exception_ptr_available<std::decay_t<T>>::type;
|
||||
};
|
||||
template <class T> constexpr bool is_exception_ptr_available_v = detail::_is_exception_ptr_available<std::decay<T>>::value;
|
||||
template <class T> constexpr bool is_exception_ptr_available_v = detail::_is_exception_ptr_available<std::decay_t<T>>::value;
|
||||
|
||||
|
||||
} // namespace trait
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Try operation macros
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
|
||||
File Created: July 2017
|
||||
|
||||
|
||||
@@ -33,52 +33,119 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "success_failure.hpp"
|
||||
|
||||
namespace std // NOLINT
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
template <class T, class E> class expected;
|
||||
template <class E> class unexpected;
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().as_failure()))
|
||||
inline decltype(auto) try_operation_return_as(T &&v)
|
||||
{
|
||||
return static_cast<T &&>(v).as_failure();
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class E> inline auto try_operation_return_as(const std::experimental::expected<T, E> &v)
|
||||
{
|
||||
return std::experimental::unexpected<E>(v.error());
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
template <class T, class E> inline auto try_operation_return_as(std::experimental::expected<T, E> &&v)
|
||||
{
|
||||
return std::experimental::unexpected<E>(static_cast<std::experimental::expected<T, E> &&>(v).error());
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct has_value_overload
|
||||
{
|
||||
};
|
||||
struct as_failure_overload
|
||||
{
|
||||
};
|
||||
struct assume_error_overload
|
||||
{
|
||||
};
|
||||
struct error_overload
|
||||
{
|
||||
};
|
||||
struct assume_value_overload
|
||||
{
|
||||
};
|
||||
struct value_overload
|
||||
{
|
||||
};
|
||||
//#ifdef __APPLE__
|
||||
// BOOST_OUTCOME_TEMPLATE(class T, class R = decltype(std::declval<T>()._xcode_workaround_as_failure()))
|
||||
//#else
|
||||
BOOST_OUTCOME_TEMPLATE(class T, class R = decltype(std::declval<T>().as_failure()))
|
||||
//#endif
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(BOOST_OUTCOME_V2_NAMESPACE::is_failure_type<R>))
|
||||
constexpr inline bool has_as_failure(int /*unused */) { return true; }
|
||||
template <class T> constexpr inline bool has_as_failure(...) { return false; }
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().assume_error()))
|
||||
constexpr inline bool has_assume_error(int /*unused */) { return true; }
|
||||
template <class T> constexpr inline bool has_assume_error(...) { return false; }
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().error()))
|
||||
constexpr inline bool has_error(int /*unused */) { return true; }
|
||||
template <class T> constexpr inline bool has_error(...) { return false; }
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().assume_value()))
|
||||
inline decltype(auto) try_extract_value(T &&v) { return static_cast<T &&>(v).assume_value(); }
|
||||
|
||||
template <class T, class... Args> inline decltype(auto) try_extract_value(T &&v, Args &&... /*unused*/) { return static_cast<T &&>(v).value(); }
|
||||
constexpr inline bool has_assume_value(int /*unused */) { return true; }
|
||||
template <class T> constexpr inline bool has_assume_value(...) { return false; }
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().value()))
|
||||
constexpr inline bool has_value(int /*unused */) { return true; }
|
||||
template <class T> constexpr inline bool has_value(...) { return false; }
|
||||
} // namespace detail
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().has_value()))
|
||||
constexpr inline bool try_operation_has_value(T &&v, detail::has_value_overload = {})
|
||||
{
|
||||
return v.has_value();
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::has_as_failure<T>(5)))
|
||||
constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::as_failure_overload = {})
|
||||
{
|
||||
return static_cast<T &&>(v).as_failure();
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!detail::has_as_failure<T>(5) && detail::has_assume_error<T>(5)))
|
||||
constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::assume_error_overload = {})
|
||||
{
|
||||
return failure(static_cast<T &&>(v).assume_error());
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!detail::has_as_failure<T>(5) && !detail::has_assume_error<T>(5) && detail::has_error<T>(5)))
|
||||
constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::error_overload = {})
|
||||
{
|
||||
return failure(static_cast<T &&>(v).error());
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::has_assume_value<T>(5)))
|
||||
constexpr inline decltype(auto) try_operation_extract_value(T &&v, detail::assume_value_overload = {})
|
||||
{
|
||||
return static_cast<T &&>(v).assume_value();
|
||||
}
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
BOOST_OUTCOME_TEMPLATE(class T)
|
||||
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!detail::has_assume_value<T>(5) && detail::has_value<T>(5)))
|
||||
constexpr inline decltype(auto) try_operation_extract_value(T &&v, detail::value_overload = {})
|
||||
{
|
||||
return static_cast<T &&>(v).value();
|
||||
}
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||
#endif
|
||||
|
||||
|
||||
#define BOOST_OUTCOME_TRY_GLUE2(x, y) x##y
|
||||
#define BOOST_OUTCOME_TRY_GLUE(x, y) BOOST_OUTCOME_TRY_GLUE2(x, y)
|
||||
#define BOOST_OUTCOME_TRY_UNIQUE_NAME BOOST_OUTCOME_TRY_GLUE(_outcome_try_unique_name_temporary, __COUNTER__)
|
||||
@@ -90,49 +157,147 @@ BOOST_OUTCOME_V2_NAMESPACE_END
|
||||
#define BOOST_OUTCOME_TRY_OVERLOAD_MACRO1(name, count) BOOST_OUTCOME_TRY_OVERLOAD_MACRO2(name, count)
|
||||
#define BOOST_OUTCOME_TRY_OVERLOAD_MACRO(name, count) BOOST_OUTCOME_TRY_OVERLOAD_MACRO1(name, count)
|
||||
#define BOOST_OUTCOME_TRY_OVERLOAD_GLUE(x, y) x y
|
||||
#define BOOST_OUTCOME_TRY_CALL_OVERLOAD(name, ...) BOOST_OUTCOME_TRY_OVERLOAD_GLUE(BOOST_OUTCOME_TRY_OVERLOAD_MACRO(name, BOOST_OUTCOME_TRY_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
|
||||
#define BOOST_OUTCOME_TRY_CALL_OVERLOAD(name, ...) \
|
||||
BOOST_OUTCOME_TRY_OVERLOAD_GLUE(BOOST_OUTCOME_TRY_OVERLOAD_MACRO(name, BOOST_OUTCOME_TRY_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||
#define _OUTCOME_TRY_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
|
||||
#define _OUTCOME_TRY_EXPAND_ARGS(args) _OUTCOME_TRY_RETURN_ARG_COUNT args
|
||||
#define _OUTCOME_TRY_COUNT_ARGS_MAX8(...) _OUTCOME_TRY_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
#define _OUTCOME_TRY_OVERLOAD_MACRO2(name, count) name##count
|
||||
#define _OUTCOME_TRY_OVERLOAD_MACRO1(name, count) _OUTCOME_TRY_OVERLOAD_MACRO2(name, count)
|
||||
#define _OUTCOME_TRY_OVERLOAD_MACRO(name, count) _OUTCOME_TRY_OVERLOAD_MACRO1(name, count)
|
||||
#define _OUTCOME_TRY_OVERLOAD_GLUE(x, y) x y
|
||||
#define _OUTCOME_TRY_CALL_OVERLOAD(name, ...) \
|
||||
_OUTCOME_TRY_OVERLOAD_GLUE(_OUTCOME_TRY_OVERLOAD_MACRO(name, _OUTCOME_TRY_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
|
||||
|
||||
#if !defined(BOOST_OUTCOME_TRY_LIKELY_IF) && defined(__has_cpp_attribute)
|
||||
#if __has_cpp_attribute(likely)
|
||||
#define BOOST_OUTCOME_TRY_LIKELY_IF(...) if(__VA_ARGS__) [[likely]]
|
||||
#endif
|
||||
#endif
|
||||
#ifndef BOOST_OUTCOME_TRY_LIKELY_IF
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define BOOST_OUTCOME_TRY_LIKELY_IF(...) if(__builtin_expect(!!(__VA_ARGS__), true))
|
||||
#else
|
||||
#define BOOST_OUTCOME_TRY_LIKELY_IF(...) if(__VA_ARGS__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BOOST_OUTCOME_TRYV2(unique, ...) \
|
||||
auto && (unique) = (__VA_ARGS__); \
|
||||
if(!(unique).has_value()) \
|
||||
return BOOST_OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(unique) &&>(unique))
|
||||
#define BOOST_OUTCOME_TRY2(unique, v, ...) \
|
||||
BOOST_OUTCOME_TRYV2(unique, __VA_ARGS__); \
|
||||
auto && (v) = BOOST_OUTCOME_V2_NAMESPACE::detail::try_extract_value(static_cast<decltype(unique) &&>(unique))
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK(...) __VA_ARGS__
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE3(unique, ...) auto unique = (__VA_ARGS__)
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE2(x) x
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE(unique, x, ...) BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE2(BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE3(unique, __VA_ARGS__))
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED3(unique, x, y, ...) x unique = (__VA_ARGS__)
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED2(x) x
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED(unique, ...) \
|
||||
BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED2(BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED3(unique, __VA_ARGS__))
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE1(...) BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE2(...) BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED
|
||||
#define BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE(unique, spec, ...) \
|
||||
_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE, BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK spec) \
|
||||
(unique, BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK spec, __VA_ARGS__)
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
// Use if(!expr); else as some compilers assume else clauses are always unlikely
|
||||
#define BOOST_OUTCOME_TRYV2_SUCCESS_LIKELY(unique, retstmt, spec, ...) \
|
||||
BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE(unique, spec, __VA_ARGS__); \
|
||||
BOOST_OUTCOME_TRY_LIKELY_IF(::BOOST_OUTCOME_V2_NAMESPACE::try_operation_has_value(unique)); \
|
||||
else \
|
||||
{ /* works around ICE in GCC's coroutines implementation */ \
|
||||
auto unique##_f(::BOOST_OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(unique) &&>(unique))); \
|
||||
retstmt unique##_f; \
|
||||
}
|
||||
#define BOOST_OUTCOME_TRYV3_FAILURE_LIKELY(unique, retstmt, spec, ...) \
|
||||
BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE(unique, spec, __VA_ARGS__); \
|
||||
BOOST_OUTCOME_TRY_LIKELY_IF(!BOOST_OUTCOME_V2_NAMESPACE::try_operation_has_value(unique)) \
|
||||
{ /* works around ICE in GCC's coroutines implementation */ \
|
||||
auto unique##_f(::BOOST_OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(unique) &&>(unique))); \
|
||||
retstmt unique##_f; \
|
||||
}
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
#define BOOST_OUTCOME_TRY2_VAR_SECOND2(x, var) var
|
||||
#define BOOST_OUTCOME_TRY2_VAR_SECOND3(x, y, ...) x y
|
||||
#define BOOST_OUTCOME_TRY2_VAR(spec) _OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_TRY2_VAR_SECOND, BOOST_OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK spec, spec)
|
||||
#define BOOST_OUTCOME_TRY2_SUCCESS_LIKELY(unique, retstmt, var, ...) \
|
||||
BOOST_OUTCOME_TRYV2_SUCCESS_LIKELY(unique, retstmt, var, __VA_ARGS__); \
|
||||
BOOST_OUTCOME_TRY2_VAR(var) = ::BOOST_OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(unique) &&>(unique))
|
||||
#define BOOST_OUTCOME_TRY2_FAILURE_LIKELY(unique, retstmt, var, ...) \
|
||||
BOOST_OUTCOME_TRYV3_FAILURE_LIKELY(unique, retstmt, var, __VA_ARGS__); \
|
||||
BOOST_OUTCOME_TRY2_VAR(var) = ::BOOST_OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(unique) &&>(unique))
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRYV(...) BOOST_OUTCOME_TRYV2(BOOST_OUTCOME_TRY_UNIQUE_NAME, __VA_ARGS__)
|
||||
#define BOOST_OUTCOME_TRYV(...) BOOST_OUTCOME_TRYV2_SUCCESS_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, deduce, __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRYV_FAILURE_LIKELY(...) BOOST_OUTCOME_TRYV3_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, deduce, __VA_ARGS__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRYV(...) BOOST_OUTCOME_TRYV2_SUCCESS_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, deduce, __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRYV_FAILURE_LIKELY(...) BOOST_OUTCOME_TRYV3_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, deduce, __VA_ARGS__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRYV2(s, ...) BOOST_OUTCOME_TRYV2_SUCCESS_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, (s, ), __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRYV2_FAILURE_LIKELY(s, ...) BOOST_OUTCOME_TRYV3_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, (s, ), __VA_ARGS__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRYV2(s, ...) BOOST_OUTCOME_TRYV2_SUCCESS_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, (s, ), __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRYV2_FAILURE_LIKELY(s, ...) BOOST_OUTCOME_TRYV3_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, s(, ), __VA_ARGS__)
|
||||
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
#define BOOST_OUTCOME_TRYX2(unique, retstmt, ...) \
|
||||
({ \
|
||||
BOOST_OUTCOME_TRYV2_SUCCESS_LIKELY(unique, retstmt, deduce, __VA_ARGS__); \
|
||||
::BOOST_OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(unique) &&>(unique)); \
|
||||
})
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRYX(...) \
|
||||
({ \
|
||||
auto &&res = (__VA_ARGS__); \
|
||||
if(!res.has_value()) \
|
||||
return BOOST_OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(res) &&>(res)); \
|
||||
BOOST_OUTCOME_V2_NAMESPACE::detail::try_extract_value(static_cast<decltype(res) &&>(res)); \
|
||||
\
|
||||
})
|
||||
#define BOOST_OUTCOME_TRYX(...) BOOST_OUTCOME_TRYX2(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, __VA_ARGS__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRYX(...) BOOST_OUTCOME_TRYX2(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRYA(v, ...) BOOST_OUTCOME_TRY2(BOOST_OUTCOME_TRY_UNIQUE_NAME, v, __VA_ARGS__)
|
||||
#define BOOST_OUTCOME_TRYA(v, ...) BOOST_OUTCOME_TRY2_SUCCESS_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, v, __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRYA_FAILURE_LIKELY(v, ...) BOOST_OUTCOME_TRY2_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, v, __VA_ARGS__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRYA(v, ...) BOOST_OUTCOME_TRY2_SUCCESS_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, v, __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(v, ...) BOOST_OUTCOME_TRY2_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, v, __VA_ARGS__)
|
||||
|
||||
|
||||
#define BOOST_OUTCOME_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) BOOST_OUTCOME_TRYA(a, b, c, d, e, f, g, h)
|
||||
#define BOOST_OUTCOME_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) BOOST_OUTCOME_TRYA(a, b, c, d, e, f, g)
|
||||
@@ -142,9 +307,132 @@ SIGNATURE NOT RECOGNISED
|
||||
#define BOOST_OUTCOME_TRY_INVOKE_TRY3(a, b, c) BOOST_OUTCOME_TRYA(a, b, c)
|
||||
#define BOOST_OUTCOME_TRY_INVOKE_TRY2(a, b) BOOST_OUTCOME_TRYA(a, b)
|
||||
#define BOOST_OUTCOME_TRY_INVOKE_TRY1(a) BOOST_OUTCOME_TRYV(a)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_TRY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) BOOST_OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) BOOST_OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) BOOST_OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) BOOST_OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e)
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) BOOST_OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d)
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) BOOST_OUTCOME_TRYA_FAILURE_LIKELY(a, b, c)
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) BOOST_OUTCOME_TRYA_FAILURE_LIKELY(a, b)
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) BOOST_OUTCOME_TRYV_FAILURE_LIKELY(a)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRY_FAILURE_LIKELY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) BOOST_OUTCOME_CO_TRYA(a, b, c, d, e, f, g, h)
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) BOOST_OUTCOME_CO_TRYA(a, b, c, d, e, f, g)
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY6(a, b, c, d, e, f) BOOST_OUTCOME_CO_TRYA(a, b, c, d, e, f)
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY5(a, b, c, d, e) BOOST_OUTCOME_CO_TRYA(a, b, c, d, e)
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY4(a, b, c, d) BOOST_OUTCOME_CO_TRYA(a, b, c, d)
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY3(a, b, c) BOOST_OUTCOME_CO_TRYA(a, b, c)
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY2(a, b) BOOST_OUTCOME_CO_TRYA(a, b)
|
||||
#define BOOST_OUTCOME_CO_TRY_INVOKE_TRY1(a) BOOST_OUTCOME_CO_TRYV(a)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_CO_TRY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_TRY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e)
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d)
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c)
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) BOOST_OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b)
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) BOOST_OUTCOME_CO_TRYV_FAILURE_LIKELY(a)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_TRYA(v, ...) BOOST_OUTCOME_TRY2_SUCCESS_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, deduce, auto &&v, __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_TRYA_FAILURE_LIKELY(v, ...) BOOST_OUTCOME_TRY2_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, return, deduce, auto &&v, __VA_ARGS__)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_CO_TRYA(v, ...) BOOST_OUTCOME_TRY2_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_return, deduce, auto &&v, __VA_ARGS__)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_CO_TRYA_FAILURE_LIKELY(v, ...) BOOST_OUTCOME_TRY2_FAILURE_LIKELY(BOOST_OUTCOME_TRY_UNIQUE_NAME, co_retrn, deduce, auto &&v, __VA_ARGS__)
|
||||
|
||||
|
||||
#define OUTCOME21_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_TRYA(a, b, c, d, e, f, g, h)
|
||||
#define OUTCOME21_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_TRYA(a, b, c, d, e, f, g)
|
||||
#define OUTCOME21_TRY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_TRYA(a, b, c, d, e, f)
|
||||
#define OUTCOME21_TRY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_TRYA(a, b, c, d, e)
|
||||
#define OUTCOME21_TRY_INVOKE_TRY4(a, b, c, d) OUTCOME21_TRYA(a, b, c, d)
|
||||
#define OUTCOME21_TRY_INVOKE_TRY3(a, b, c) OUTCOME21_TRYA(a, b, c)
|
||||
#define OUTCOME21_TRY_INVOKE_TRY2(a, b) OUTCOME21_TRYA(a, b)
|
||||
#define OUTCOME21_TRY_INVOKE_TRY1(a) BOOST_OUTCOME_TRYV(a)
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_TRY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e)
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d)
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c)
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) OUTCOME21_TRYA_FAILURE_LIKELY(a, b)
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) BOOST_OUTCOME_TRYV_FAILURE_LIKELY(a)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_TRY_FAILURE_LIKELY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_CO_TRYA(a, b, c, d, e, f, g, h)
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_CO_TRYA(a, b, c, d, e, f, g)
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_CO_TRYA(a, b, c, d, e, f)
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_CO_TRYA(a, b, c, d, e)
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY4(a, b, c, d) OUTCOME21_CO_TRYA(a, b, c, d)
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY3(a, b, c) OUTCOME21_CO_TRYA(a, b, c)
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY2(a, b) OUTCOME21_CO_TRYA(a, b)
|
||||
#define OUTCOME21_CO_TRY_INVOKE_TRY1(a) BOOST_OUTCOME_CO_TRYV(a)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_CO_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_CO_TRY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e)
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d)
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c)
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b)
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) BOOST_OUTCOME_CO_TRYV_FAILURE_LIKELY(a)
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL
|
||||
SIGNATURE NOT RECOGNISED
|
||||
*/
|
||||
#define OUTCOME21_CO_TRY_FAILURE_LIKELY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
|
||||
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Tries to convert an exception ptr into its equivalent error code
|
||||
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
|
||||
(C) 2017-2023 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
|
||||
File Created: July 2017
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include "config.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_MAJOR 2
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_MINOR 0
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_PATCH 0
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#define BOOST_OUTCOME_VERSION_REVISION 0 // Revision version for cmake and DLL version stamping
|
||||
|
||||
/*! AWAITING HUGO JSON CONVERSION TOOL */
|
||||
#ifndef BOOST_OUTCOME_DISABLE_ABI_PERMUTATION
|
||||
#define BOOST_OUTCOME_UNSTABLE_VERSION
|
||||
#endif
|
||||
Reference in New Issue
Block a user