updated boost on windows

This commit is contained in:
Bassem Girgis
2019-08-13 21:48:48 -05:00
parent 7d77d485fd
commit b40a3bee82
5162 changed files with 473027 additions and 116452 deletions

View File

@@ -0,0 +1,97 @@
/* Exception types throwable
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BAD_ACCESS_HPP
#define BOOST_OUTCOME_BAD_ACCESS_HPP
#include "config.hpp"
#include <stdexcept>
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition bad_result_access. Potential doc page: `bad_result_access`
*/
class BOOST_OUTCOME_SYMBOL_VISIBLE bad_result_access : public std::logic_error
{
public:
explicit bad_result_access(const char *what)
: std::logic_error(what)
{
}
};
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class S> bad_result_access_with. Potential doc page: `bad_result_access_with<EC>`
*/
template <class S> class BOOST_OUTCOME_SYMBOL_VISIBLE bad_result_access_with : public bad_result_access
{
S _error;
public:
explicit bad_result_access_with(S v)
: bad_result_access("no value")
, _error(std::move(v))
{
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
const S &error() const & { return _error; }
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
S &error() & { return _error; }
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
const S &&error() const && { return _error; }
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
S &&error() && { return _error; }
};
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition bad_outcome_access. Potential doc page: `bad_outcome_access`
*/
class BOOST_OUTCOME_SYMBOL_VISIBLE bad_outcome_access : public std::logic_error
{
public:
explicit bad_outcome_access(const char *what)
: std::logic_error(what)
{
}
};
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,554 @@
/* A very simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BASIC_RESULT_HPP
#define BOOST_OUTCOME_BASIC_RESULT_HPP
#include "config.hpp"
#include "convert.hpp"
#include "detail/basic_result_final.hpp"
#include "policy/all_narrow.hpp"
#include "policy/terminate.hpp"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation" // Standardese markup confuses clang
#endif
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
template <class 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
class basic_result;
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 value converting constructor to be available. Weakened to allow result<int, C enum>.
template <class T>
static constexpr bool enable_value_converting_constructor = //
implicit_constructors_enabled //
&& !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
&& !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
// Predicate for the error converting constructor to be available. Weakened to allow result<int, C enum>.
template <class T>
static constexpr bool enable_error_converting_constructor = //
implicit_constructors_enabled //
&& !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
&& !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
// 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
// Predicate for the converting copy 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
;
// 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, //
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;
};
template <class T, class U> constexpr inline const U &extract_value_from_success(const success_type<U> &v) { return v.value(); }
template <class T, class U> constexpr inline U &&extract_value_from_success(success_type<U> &&v) { return static_cast<success_type<U> &&>(v).value(); }
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 V> constexpr inline T extract_error_from_failure(const failure_type<void, V> & /*unused*/) { return T{}; }
template <class T> struct is_basic_result
{
static constexpr bool value = false;
};
template <class R, class S, class T> struct is_basic_result<basic_result<R, S, T>>
{
static constexpr bool value = true;
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
type alias template <class T> is_basic_result. Potential doc page: `is_basic_result<T>`
*/
template <class T> using is_basic_result = detail::is_basic_result<std::decay_t<T>>;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> static constexpr bool is_basic_result_v = detail::is_basic_result<std::decay_t<T>>::value;
/*! 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 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); }
} // 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
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>;
struct implicit_constructors_disabled_tag
{
};
struct value_converting_constructor_tag
{
};
struct error_converting_constructor_tag
{
};
struct error_condition_converting_constructor_tag
{
};
struct explicit_valueornone_converting_constructor_tag
{
};
struct explicit_valueorerror_converting_constructor_tag
{
};
public:
using value_type = R;
using error_type = S;
using value_type_if_enabled = typename base::_value_type;
using error_type_if_enabled = typename base::_error_type;
template <class T, class U = S, class V = NoValuePolicy> using rebind = basic_result<T, U, V>;
protected:
// Requirement predicates for result.
struct predicate
{
using base = detail::result_predicates<value_type, error_type>;
// Predicate for any constructors to be available at all
static constexpr bool constructors_enabled = !std::is_same<std::decay_t<value_type>, std::decay_t<error_type>>::value;
// Predicate for implicit constructors to be available at all
static constexpr bool implicit_constructors_enabled = constructors_enabled && base::implicit_constructors_enabled;
// Predicate for the value converting constructor to be available.
template <class T>
static constexpr bool enable_value_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_result>::value // not my type
&& base::template enable_value_converting_constructor<T>;
// Predicate for the error converting constructor to be available.
template <class T>
static constexpr bool enable_error_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_result>::value // not my type
&& base::template enable_error_converting_constructor<T>;
// Predicate for the error condition converting constructor to be available.
template <class ErrorCondEnum>
static constexpr bool enable_error_condition_converting_constructor = //
constructors_enabled //
&& !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.
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 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);
// 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);
// Predicate for the implicit converting inplace constructor to be available.
template <class... Args>
static constexpr bool enable_inplace_value_error_constructor = //
constructors_enabled //
&&base::template enable_inplace_value_error_constructor<Args...>;
template <class... Args> using choose_inplace_value_error_constructor = typename base::template choose_inplace_value_error_constructor<Args...>;
};
public:
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result() = delete;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result(basic_result && /*unused*/) = default; // NOLINT
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result(const basic_result & /*unused*/) = default;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result &operator=(basic_result && /*unused*/) = default; // NOLINT
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result &operator=(const basic_result & /*unused*/) = default;
~basic_result() = default;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class Arg, class... Args)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!predicate::constructors_enabled && (sizeof...(Args) >= 0)))
basic_result(Arg && /*unused*/, Args &&... /*unused*/) = delete; // NOLINT basic_result<T, T> is NOT SUPPORTED, see docs!
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED((predicate::constructors_enabled && !predicate::implicit_constructors_enabled //
&& (detail::is_implicitly_constructible<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!
/*! 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)}
{
using namespace hooks;
hook_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)}
{
using namespace hooks;
hook_result_construction(this, static_cast<T &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class ErrorCondEnum)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), //
BOOST_OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor<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)}
{
using namespace hooks;
hook_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_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))}
{
}
/*! 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(const basic_result<T, U, V> &o) noexcept(std::is_nothrow_constructible<value_type, T>::value &&std::is_nothrow_constructible<error_type, U>::value)
: base{typename base::compatible_conversion_tag(), o}
{
using namespace hooks;
hook_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)
: 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));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class... Args)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<Args...>))
constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args...>::value)
: base{_, static_cast<Args &&>(args)...}
{
using namespace hooks;
hook_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)
: 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)...);
}
/*! 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)
: base{_, static_cast<Args &&>(args)...}
{
using namespace hooks;
hook_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)
: 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)...);
}
/*! 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)...)
{
/* 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>}
{
using namespace hooks;
hook_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)}
{
using namespace hooks;
hook_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))}
{
using namespace hooks;
hook_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)}
{
using namespace hooks;
hook_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))}
{
using namespace hooks;
hook_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)
{
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);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
auto as_failure() const & { return failure(this->assume_error()); }
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
auto as_failure() && { return failure(static_cast<basic_result &&>(*this).assume_error()); }
};
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class P> inline void swap(basic_result<R, S, P> &a, basic_result<R, S, P> &b) noexcept(noexcept(a.swap(b)))
{
a.swap(b);
}
#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_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_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!");
static_assert(std::is_trivially_copy_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy assignable!");
static_assert(std::is_trivially_move_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move assignable!");
// Also check is standard layout
static_assert(std::is_standard_layout<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not a standard layout type!");
#endif
BOOST_OUTCOME_V2_NAMESPACE_END
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif

View File

@@ -0,0 +1,57 @@
/* A less simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BOOST_OUTCOME_HPP
#define BOOST_OUTCOME_BOOST_OUTCOME_HPP
#include "std_outcome.hpp"
#include "boost_result.hpp"
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)); }
} // namespace system
} // namespace boost
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
/*! 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>> //
using boost_outcome = basic_outcome<R, S, P, NoValuePolicy>;
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,175 @@
/* A very simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BOOST_RESULT_HPP
#define BOOST_OUTCOME_BOOST_RESULT_HPP
#include "config.hpp"
#include "boost/exception_ptr.hpp"
#include "boost/system/system_error.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
namespace policy
{
namespace detail
{
/* Pass through `make_error_code` function for `boost::system::error_code`.
*/
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
BOOST_OUTCOME_V2_NAMESPACE_END
#include "std_result.hpp"
// ADL injection of outcome_throw_as_system_error_with_payload
namespace boost
{
namespace system
{
inline void outcome_throw_as_system_error_with_payload(const error_code &error) { BOOST_OUTCOME_THROW_EXCEPTION(system_error(error)); }
namespace errc
{
BOOST_OUTCOME_TEMPLATE(class Error)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(is_error_code_enum<std::decay_t<Error>>::value || is_error_condition_enum<std::decay_t<Error>>::value))
inline void outcome_throw_as_system_error_with_payload(Error &&error) { BOOST_OUTCOME_THROW_EXCEPTION(system_error(make_error_code(error))); }
} // namespace errc
} // namespace system
} // namespace boost
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
// Customise _set_error_is_errno
template <class State> constexpr inline void _set_error_is_errno(State &state, const boost::system::error_code &error)
{
if(error.category() == boost::system::generic_category()
#ifndef _WIN32
|| error.category() == boost::system::system_category()
#endif
)
{
state._status |= status_error_is_errno;
}
}
template <class State> constexpr inline void _set_error_is_errno(State &state, const boost::system::error_condition &error)
{
if(error.category() == boost::system::generic_category()
#ifndef _WIN32
|| error.category() == boost::system::system_category()
#endif
)
{
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 |= status_error_is_errno; }
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
namespace trait
{
namespace detail
{
// Shortcut these for lower build impact
template <> struct _is_error_code_available<boost::system::error_code>
{
static constexpr bool value = true;
};
template <> struct _is_exception_ptr_available<boost::exception_ptr>
{
static constexpr bool value = true;
};
} // namespace detail
// boost::system::error_code is an error type
template <> struct is_error_type<boost::system::error_code>
{
static constexpr bool value = true;
};
// boost::system::error_code::errc_t is an error type
template <> struct is_error_type<boost::system::errc::errc_t>
{
static constexpr bool value = true;
};
// boost::exception_ptr is an error types
template <> struct is_error_type<boost::exception_ptr>
{
static constexpr bool value = true;
};
// For boost::system::error_code, boost::system::is_error_condition_enum<> is the trait we want.
template <class Enum> struct is_error_type_enum<boost::system::error_code, Enum>
{
static constexpr bool value = boost::system::is_error_condition_enum<Enum>::value;
};
} // namespace trait
/*! 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
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
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>>;
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,323 @@
/* Configure Boost.Outcome with Boost
(C) 2015-2019 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
File Created: August 2015
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_V2_CONFIG_HPP
#define BOOST_OUTCOME_V2_CONFIG_HPP
#include "version.hpp"
// Pull in detection of __MINGW64_VERSION_MAJOR
#if defined(__MINGW32__) && !defined(DOXYGEN_IS_IN_THE_HOUSE)
#include <_mingw.h>
#endif
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
#error Boost.Outcome needs variadic template support in the compiler
#endif
#if defined(BOOST_NO_CXX14_CONSTEXPR) && _MSC_FULL_VER < 191100000
#error Boost.Outcome needs constexpr (C++ 14) support in the compiler
#endif
#ifdef BOOST_NO_CXX14_VARIABLE_TEMPLATES
#error Boost.Outcome needs variable template support in the compiler
#endif
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 6
#error Due to a bug in nested template variables parsing, Boost.Outcome does not work on GCCs earlier than v6.
#endif
#ifndef BOOST_OUTCOME_SYMBOL_VISIBLE
#define BOOST_OUTCOME_SYMBOL_VISIBLE BOOST_SYMBOL_VISIBLE
#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)
#define BOOST_OUTCOME_NODISCARD [[nodiscard]]
#endif
#elif defined(__clang__)
#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")
#endif
#endif
#ifndef BOOST_OUTCOME_NODISCARD
#define BOOST_OUTCOME_NODISCARD
#endif
#ifndef BOOST_OUTCOME_THREAD_LOCAL
#ifndef BOOST_NO_CXX11_THREAD_LOCAL
#define BOOST_OUTCOME_THREAD_LOCAL thread_local
#else
#if defined(_MSC_VER)
#define BOOST_OUTCOME_THREAD_LOCAL __declspec(thread)
#elif defined(__GNUC__)
#define BOOST_OUTCOME_THREAD_LOCAL __thread
#else
#error Unknown compiler, cannot set BOOST_OUTCOME_THREAD_LOCAL
#endif
#endif
#endif
// Can't use the QuickCppLib preprocessor metaprogrammed Concepts TS support, so ...
#ifndef BOOST_OUTCOME_TEMPLATE
#define BOOST_OUTCOME_TEMPLATE(...) template <__VA_ARGS__
#endif
#ifndef BOOST_OUTCOME_TREQUIRES
#define BOOST_OUTCOME_TREQUIRES(...) , __VA_ARGS__ >
#endif
#ifndef BOOST_OUTCOME_TEXPR
#define BOOST_OUTCOME_TEXPR(...) typename = decltype(__VA_ARGS__)
#endif
#ifndef BOOST_OUTCOME_TPRED
#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__
#else
#define BOOST_OUTCOME_REQUIRES(...)
#endif
#endif
namespace boost
{
#define BOOST_OUTCOME_V2
//! The Boost.Outcome namespace
namespace outcome_v2
{
}
}
/*! 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 \
{
/*! 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 \
{
/*! \brief Expands into the appropriate namespace markup to exit the Boost.Outcome v2 namespace.
\ingroup config
*/
#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 <type_traits>
#ifndef BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE
#if defined(_MSC_VER) && _HAS_CXX17
#define BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE 1 // MSVC always has std::in_place_type
#elif __cplusplus >= 201700
// libstdc++ before GCC 6 doesn't have it, despite claiming C++ 17 support
#ifdef __has_include
#if !__has_include(<variant>)
#define BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE 0 // must have it if <variant> is present
#endif
#endif
#ifndef BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE
#define BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE 1
#endif
#else
#define BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE 0
#endif
#endif
#if BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE
#include <utility> // for in_place_type_t
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
template <class T> using in_place_type_t = std::in_place_type_t<T>;
using std::in_place_type;
BOOST_OUTCOME_V2_NAMESPACE_END
#else
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
//! Aliases `std::in_place_type_t<T>` if on C++ 17 or later, else defined locally.
template <class T> struct in_place_type_t
{
explicit in_place_type_t() = default;
};
//! Aliases `std::in_place_type<T>` if on C++ 17 or later, else defined locally.
template <class T> constexpr in_place_type_t<T> in_place_type{};
BOOST_OUTCOME_V2_NAMESPACE_END
#endif
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
namespace detail
{
// Test if type is an in_place_type_t
template <class T> struct is_in_place_type_t
{
static constexpr bool value = false;
};
template <class U> struct is_in_place_type_t<in_place_type_t<U>>
{
static constexpr bool value = true;
};
// Replace void with constructible void_type
struct empty_type
{
};
struct void_type
{
// We always compare true to another instance of me
constexpr bool operator==(void_type /*unused*/) const noexcept { return true; }
constexpr bool operator!=(void_type /*unused*/) const noexcept { return false; }
};
template <class T> using devoid = std::conditional_t<std::is_void<T>::value, void_type, T>;
template <class Output, class Input> using rebind_type5 = Output;
template <class Output, class Input>
using rebind_type4 = std::conditional_t< //
std::is_volatile<Input>::value, //
std::add_volatile_t<rebind_type5<Output, std::remove_volatile_t<Input>>>, //
rebind_type5<Output, Input>>;
template <class Output, class Input>
using rebind_type3 = std::conditional_t< //
std::is_const<Input>::value, //
std::add_const_t<rebind_type4<Output, std::remove_const_t<Input>>>, //
rebind_type4<Output, Input>>;
template <class Output, class Input>
using rebind_type2 = std::conditional_t< //
std::is_lvalue_reference<Input>::value, //
std::add_lvalue_reference_t<rebind_type3<Output, std::remove_reference_t<Input>>>, //
rebind_type3<Output, Input>>;
template <class Output, class Input>
using rebind_type = std::conditional_t< //
std::is_rvalue_reference<Input>::value, //
std::add_rvalue_reference_t<rebind_type2<Output, std::remove_reference_t<Input>>>, //
rebind_type2<Output, Input>>;
// static_assert(std::is_same_v<rebind_type<int, volatile const double &&>, volatile const int &&>, "");
/* True if type is the same or constructible. Works around a bug where clang + libstdc++
pukes on std::is_constructible<filesystem::path, void> (this bug is fixed upstream).
*/
template <class T, class U> struct _is_explicitly_constructible
{
static constexpr bool value = std::is_constructible<T, U>::value;
};
template <class T> struct _is_explicitly_constructible<T, void>
{
static constexpr bool value = false;
};
template <> struct _is_explicitly_constructible<void, void>
{
static constexpr bool value = false;
};
template <class T, class U> static constexpr bool is_explicitly_constructible = _is_explicitly_constructible<T, U>::value;
template <class T, class U> struct _is_implicitly_constructible
{
static constexpr bool value = std::is_convertible<U, T>::value;
};
template <class T> struct _is_implicitly_constructible<T, void>
{
static constexpr bool value = false;
};
template <> struct _is_implicitly_constructible<void, void>
{
static constexpr bool value = false;
};
template <class T, class U> static constexpr bool is_implicitly_constructible = _is_implicitly_constructible<T, U>::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
#elif __cplusplus >= 201700
// libstdc++ before GCC 6 doesn't have it, despite claiming C++ 17 support
#ifdef __has_include
#if !__has_include(<variant>)
#define BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 0 // must have it if <variant> is present
#endif
#endif
#ifndef BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
#define BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 1
#endif
#else
#define BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 0
#endif
#endif
// True if type is nothrow swappable
#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
{
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>;
#endif
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#ifndef BOOST_OUTCOME_THROW_EXCEPTION
#include <boost/throw_exception.hpp>
#define BOOST_OUTCOME_THROW_EXCEPTION(expr) BOOST_THROW_EXCEPTION(expr)
#endif
#ifndef BOOST_OUTCOME_AUTO_TEST_CASE
#define BOOST_OUTCOME_AUTO_TEST_CASE(a, b) BOOST_AUTO_TEST_CASE(a)
#endif
#endif

View File

@@ -0,0 +1,128 @@
/* Says how to convert value, error and exception types
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Nov 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_CONVERT_HPP
#define BOOST_OUTCOME_CONVERT_HPP
#include "detail/basic_result_storage.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace convert
{
#if defined(__cpp_concepts)
/* The `ValueOrNone` 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)
{
{
a.has_value()
}
->bool;
{a.value()};
};
/* The `ValueOrError` 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)
{
{
a.has_value()
}
->bool;
{a.value()};
{a.error()};
};
#else
namespace detail
{
struct no_match
{
};
inline no_match match_value_or_none(...);
inline no_match match_value_or_error(...);
BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<U>().has_value()), BOOST_OUTCOME_TEXPR(std::declval<U>().value()))
inline U match_value_or_none(U &&);
BOOST_OUTCOME_TEMPLATE(class U)
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;
} // namespace detail
/* The `ValueOrNone` 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.
\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>;
#endif
namespace detail
{
template <class T, class X> struct make_type
{
template <class U> static constexpr T value(U &&v) { return T{in_place_type<typename T::value_type>, static_cast<U &&>(v).value()}; }
template <class U> static constexpr T error(U &&v) { return T{in_place_type<typename T::error_type>, static_cast<U &&>(v).error()}; }
static constexpr T error() { return T{in_place_type<typename T::error_type>}; }
};
template <class T> struct make_type<T, void>
{
template <class U> static constexpr T value(U && /*unused*/) { return T{in_place_type<typename T::value_type>}; }
template <class U> static constexpr T error(U && /*unused*/) { return T{in_place_type<typename T::error_type>}; }
static constexpr T error() { return T{in_place_type<typename T::error_type>}; }
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition value_or_error. Potential doc page: NOT FOUND
*/
template <class T, class U> struct value_or_error
{
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)); }
};
} // namespace convert
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,70 @@
/* Exception observers for outcome type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_HPP
#define BOOST_OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_HPP
#include "basic_result_storage.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class Base, class R, class S, class P, class NoValuePolicy> class basic_outcome_exception_observers : public Base
{
public:
using exception_type = P;
using Base::Base;
constexpr inline exception_type &assume_exception() & noexcept;
constexpr inline const exception_type &assume_exception() const &noexcept;
constexpr inline exception_type &&assume_exception() && noexcept;
constexpr inline const exception_type &&assume_exception() const &&noexcept;
constexpr inline exception_type &exception() &;
constexpr inline const exception_type &exception() const &;
constexpr inline exception_type &&exception() &&;
constexpr inline const exception_type &&exception() const &&;
};
// Exception observers not present
template <class Base, class R, class S, class NoValuePolicy> class basic_outcome_exception_observers<Base, R, S, void, NoValuePolicy> : public Base
{
public:
using Base::Base;
constexpr void assume_exception() const noexcept { NoValuePolicy::narrow_exception_check(this); }
constexpr void exception() const { NoValuePolicy::wide_exception_check(this); }
};
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,104 @@
/* Exception observers for outcome type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_IMPL_HPP
#define BOOST_OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_IMPL_HPP
#include "basic_outcome_exception_observers.hpp"
#include "../policy/base.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
template <class R, class S, class P, class NoValuePolicy, class Impl> inline constexpr auto &&base::_exception(Impl &&self) noexcept
{
// Impl will be some internal implementation class which has no knowledge of the _ptr stored
// beneath it. So statically cast, preserving rvalue and constness, to the derived class.
using Outcome = BOOST_OUTCOME_V2_NAMESPACE::detail::rebind_type<basic_outcome<R, S, P, NoValuePolicy>, decltype(self)>;
#if defined(_MSC_VER) && _MSC_VER < 1920
// VS2017 tries a copy construction in the correct implementation despite that Outcome is always a rvalue or lvalue ref! :(
basic_outcome<R, S, P, NoValuePolicy> &_self = (basic_outcome<R, S, P, NoValuePolicy> &) (self); // NOLINT
#else
Outcome _self = static_cast<Outcome>(self); // NOLINT
#endif
return static_cast<Outcome>(_self)._ptr;
}
} // namespace policy
namespace detail
{
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() & noexcept
{
NoValuePolicy::narrow_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() const &noexcept
{
NoValuePolicy::narrow_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() && noexcept
{
NoValuePolicy::narrow_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() const &&noexcept
{
NoValuePolicy::narrow_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() &
{
NoValuePolicy::wide_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() const &
{
NoValuePolicy::wide_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() &&
{
NoValuePolicy::wide_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() const &&
{
NoValuePolicy::wide_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,100 @@
/* Failure observers for outcome type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BASIC_OUTCOME_FAILURE_OBSERVERS_HPP
#define BOOST_OUTCOME_BASIC_OUTCOME_FAILURE_OBSERVERS_HPP
#include "basic_result_storage.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
namespace adl
{
struct search_detail_adl
{
};
BOOST_OUTCOME_TEMPLATE(class S) //
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(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
// 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
template <class S, class P> inline void _delayed_lookup_basic_outcome_failure_exception_from_error(...) = delete; // NOLINT No specialisation for these error and exception types available!
#endif
template <class exception_type> inline exception_type current_exception_or_fatal(std::exception_ptr e) { std::rethrow_exception(e); }
template <> inline std::exception_ptr current_exception_or_fatal<std::exception_ptr>(std::exception_ptr e) { return e; }
template <class Base, class R, class S, class P, class NoValuePolicy> class basic_outcome_failure_observers : public Base
{
public:
using exception_type = P;
using Base::Base;
exception_type failure() const noexcept
{
#ifndef BOOST_NO_EXCEPTIONS
try
#endif
{
if((this->_state._status & detail::status_have_exception) != 0)
{
return this->assume_exception();
}
if((this->_state._status & detail::status_have_error) != 0)
{
return _delayed_lookup_basic_outcome_failure_exception_from_error(this->assume_error(), adl::search_detail_adl());
}
return exception_type();
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...)
{
// Return the failure if exception_type is std::exception_ptr,
// otherwise terminate same as throwing an exception inside noexcept
return current_exception_or_fatal<exception_type>(std::current_exception());
}
#endif
}
};
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,98 @@
/* Error observers for a very simple basic_result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BASIC_RESULT_ERROR_OBSERVERS_HPP
#define BOOST_OUTCOME_BASIC_RESULT_ERROR_OBSERVERS_HPP
#include "basic_result_storage.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class Base, class EC, class NoValuePolicy> class basic_result_error_observers : public Base
{
public:
using error_type = EC;
using Base::Base;
constexpr error_type &assume_error() & noexcept
{
NoValuePolicy::narrow_error_check(static_cast<basic_result_error_observers &>(*this));
return this->_error;
}
constexpr const error_type &assume_error() const &noexcept
{
NoValuePolicy::narrow_error_check(static_cast<const basic_result_error_observers &>(*this));
return this->_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);
}
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);
}
constexpr error_type &error() &
{
NoValuePolicy::wide_error_check(static_cast<basic_result_error_observers &>(*this));
return this->_error;
}
constexpr const error_type &error() const &
{
NoValuePolicy::wide_error_check(static_cast<const basic_result_error_observers &>(*this));
return this->_error;
}
constexpr error_type &&error() &&
{
NoValuePolicy::wide_error_check(static_cast<basic_result_error_observers &&>(*this));
return static_cast<error_type &&>(this->_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);
}
};
template <class Base, class NoValuePolicy> class basic_result_error_observers<Base, void, NoValuePolicy> : public Base
{
public:
using Base::Base;
constexpr void assume_error() const noexcept { NoValuePolicy::narrow_error_check(*this); }
constexpr void error() const { NoValuePolicy::wide_error_check(*this); }
};
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,157 @@
/* Finaliser for a very simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BASIC_RESULT_FINAL_HPP
#define BOOST_OUTCOME_BASIC_RESULT_FINAL_HPP
#include "basic_result_error_observers.hpp"
#include "basic_result_value_observers.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class R, class EC, class NoValuePolicy> using select_basic_result_impl = basic_result_error_observers<basic_result_value_observers<basic_result_storage<R, EC, NoValuePolicy>, R, NoValuePolicy>, EC, NoValuePolicy>;
template <class R, class S, class NoValuePolicy>
class basic_result_final
#if defined(BOOST_OUTCOME_DOXYGEN_IS_IN_THE_HOUSE)
: public basic_result_error_observers<basic_result_value_observers<basic_result_storage<R, S, NoValuePolicy>, R, NoValuePolicy>, S, NoValuePolicy>
#else
: public select_basic_result_impl<R, S, NoValuePolicy>
#endif
{
using base = select_basic_result_impl<R, S, NoValuePolicy>;
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; }
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>>()), //
BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<S>>() == std::declval<detail::devoid<U>>()))
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)
{
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)
{
return this->_error == o._error;
}
return false;
}
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<R>() == std::declval<T>()))
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)
{
return this->_state._value == o.value();
}
return false;
}
constexpr bool operator==(const success_type<void> &o) const noexcept
{
(void) o;
return (this->_state._status & detail::status_have_value) != 0;
}
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)
{
return this->_error == o.error();
}
return false;
}
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>>()), //
BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<S>>() != std::declval<detail::devoid<U>>()))
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)
{
return this->_state._value != o._state._value;
}
if((this->_state._status & detail::status_have_error) != 0 && (o._state._status & detail::status_have_error) != 0)
{
return this->_error != o._error;
}
return true;
}
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<R>() != std::declval<T>()))
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)
{
return this->_state._value != o.value();
}
return false;
}
constexpr bool operator!=(const success_type<void> &o) const noexcept
{
(void) o;
return (this->_state._status & detail::status_have_value) == 0;
}
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)
{
return this->_error != o.error();
}
return true;
}
};
template <class T, class U, class V, class W> constexpr inline bool operator==(const success_type<W> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b == a; }
template <class T, class U, class V, class W> constexpr inline bool operator==(const failure_type<W, void> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b == a; }
template <class T, class U, class V, class W> constexpr inline bool operator!=(const success_type<W> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b != a; }
template <class T, class U, class V, class W> constexpr inline bool operator!=(const failure_type<W, void> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b != a; }
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,257 @@
/* Storage for a very simple basic_result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_BASIC_RESULT_STORAGE_HPP
#define BOOST_OUTCOME_BASIC_RESULT_STORAGE_HPP
#include "../success_failure.hpp"
#include "../trait.hpp"
#include "value_storage.hpp"
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;
} // 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;
} // namespace hooks
namespace policy
{
struct base;
} // 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)) //
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_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;
struct disable_in_place_value_type
{
};
struct disable_in_place_error_type
{
};
protected:
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>;
#ifdef BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE
detail::value_storage_trivial<_value_type> _state;
#else
detail::value_storage_select_impl<_value_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; }
protected:
basic_result_storage() = default;
basic_result_storage(const basic_result_storage &) = default; // NOLINT
basic_result_storage(basic_result_storage &&) = default; // NOLINT
basic_result_storage &operator=(const basic_result_storage &) = default; // NOLINT
basic_result_storage &operator=(basic_result_storage &&) = default; // NOLINT
~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)
: _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)
: _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)...)
{
_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)...}
{
_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)
: _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)
: _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)
{
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
#endif

View File

@@ -0,0 +1,100 @@
/* Value observers for a very simple basic_result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_RESULT_VALUE_OBSERVERS_HPP
#define BOOST_OUTCOME_RESULT_VALUE_OBSERVERS_HPP
#include "basic_result_storage.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class Base, class R, class NoValuePolicy> class basic_result_value_observers : public Base
{
public:
using value_type = R;
using Base::Base;
constexpr value_type &assume_value() & noexcept
{
NoValuePolicy::narrow_value_check(static_cast<basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr const value_type &assume_value() const &noexcept
{
NoValuePolicy::narrow_value_check(static_cast<const basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr value_type &&assume_value() && noexcept
{
NoValuePolicy::narrow_value_check(static_cast<basic_result_value_observers &&>(*this));
return static_cast<value_type &&>(this->_state._value); // NOLINT
}
constexpr const value_type &&assume_value() const &&noexcept
{
NoValuePolicy::narrow_value_check(static_cast<const basic_result_value_observers &&>(*this));
return static_cast<const value_type &&>(this->_state._value); // NOLINT
}
constexpr value_type &value() &
{
NoValuePolicy::wide_value_check(static_cast<basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr const value_type &value() const &
{
NoValuePolicy::wide_value_check(static_cast<const basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr value_type &&value() &&
{
NoValuePolicy::wide_value_check(static_cast<basic_result_value_observers &&>(*this));
return static_cast<value_type &&>(this->_state._value); // NOLINT
}
constexpr const value_type &&value() const &&
{
NoValuePolicy::wide_value_check(static_cast<const basic_result_value_observers &&>(*this));
return static_cast<const value_type &&>(this->_state._value); // NOLINT
}
};
template <class Base, class NoValuePolicy> class basic_result_value_observers<Base, void, NoValuePolicy> : public Base
{
public:
using Base::Base;
constexpr void assume_value() const noexcept { NoValuePolicy::narrow_value_check(*this); }
constexpr void value() const { NoValuePolicy::wide_value_check(*this); }
};
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,126 @@
/* Traits for Outcome
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: March 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_TRAIT_STD_ERROR_CODE_HPP
#define BOOST_OUTCOME_TRAIT_STD_ERROR_CODE_HPP
#include "../config.hpp"
#include <system_error>
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
namespace detail
{
// Customise _set_error_is_errno
template <class State> constexpr inline void _set_error_is_errno(State &state, const std::error_code &error)
{
if(error.category() == std::generic_category()
#ifndef _WIN32
|| error.category() == std::system_category()
#endif
)
{
state._status |= status_error_is_errno;
}
}
template <class State> constexpr inline void _set_error_is_errno(State &state, const std::error_condition &error)
{
if(error.category() == std::generic_category()
#ifndef _WIN32
|| error.category() == std::system_category()
#endif
)
{
state._status |= status_error_is_errno;
}
}
template <class State> constexpr inline void _set_error_is_errno(State &state, const std::errc & /*unused*/) { state._status |= status_error_is_errno; }
} // namespace detail
namespace policy
{
namespace detail
{
/* Pass through `make_error_code` function for `std::error_code`.
*/
inline std::error_code make_error_code(std::error_code v) { return v; }
// Try ADL, if not use fall backs above
template <class T> constexpr inline decltype(auto) error_code(T &&v) { return make_error_code(std::forward<T>(v)); }
struct std_enum_overload_tag
{
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> constexpr inline decltype(auto) error_code(T &&v) { return detail::error_code(std::forward<T>(v)); }
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
// inline void outcome_throw_as_system_error_with_payload(...) = delete; // To use the error_code_throw_as_system_error policy with a custom Error type, you must define a outcome_throw_as_system_error_with_payload() free function to say how to handle the payload
inline void outcome_throw_as_system_error_with_payload(const std::error_code &error) { BOOST_OUTCOME_THROW_EXCEPTION(std::system_error(error)); } // NOLINT
BOOST_OUTCOME_TEMPLATE(class Error)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_error_code_enum<std::decay_t<Error>>::value || std::is_error_condition_enum<std::decay_t<Error>>::value))
inline void outcome_throw_as_system_error_with_payload(Error &&error, detail::std_enum_overload_tag /*unused*/ = detail::std_enum_overload_tag()) { BOOST_OUTCOME_THROW_EXCEPTION(std::system_error(make_error_code(error))); } // NOLINT
} // namespace policy
namespace trait
{
namespace detail
{
template <> struct _is_error_code_available<std::error_code>
{
// Shortcut this for lower build impact
static constexpr bool value = true;
};
} // namespace detail
// std::error_code is an error type
template <> struct is_error_type<std::error_code>
{
static constexpr bool value = true;
};
// For std::error_code, std::is_error_condition_enum<> is the trait we want.
template <class Enum> struct is_error_type_enum<std::error_code, Enum>
{
static constexpr bool value = std::is_error_condition_enum<Enum>::value;
};
} // namespace trait
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,97 @@
/* Traits for Outcome
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: March 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_TRAIT_STD_EXCEPTION_HPP
#define BOOST_OUTCOME_TRAIT_STD_EXCEPTION_HPP
#include "../config.hpp"
#include <exception>
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
namespace policy
{
namespace detail
{
/* Pass through `make_exception_ptr` function for `std::exception_ptr`.
*/
inline std::exception_ptr make_exception_ptr(std::exception_ptr v) { return v; }
// Try ADL, if not use fall backs above
template <class T> constexpr inline decltype(auto) exception_ptr(T &&v) { return make_exception_ptr(std::forward<T>(v)); }
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> constexpr inline decltype(auto) exception_ptr(T &&v) { return detail::exception_ptr(std::forward<T>(v)); }
namespace detail
{
template <bool has_error_payload> struct _rethrow_exception
{
template <class Exception> explicit _rethrow_exception(Exception && /*unused*/) // NOLINT
{
}
};
template <> struct _rethrow_exception<true>
{
template <class Exception> explicit _rethrow_exception(Exception &&excpt) // NOLINT
{
// ADL
rethrow_exception(policy::exception_ptr(std::forward<Exception>(excpt)));
}
};
} // namespace detail
} // namespace policy
namespace trait
{
namespace detail
{
// Shortcut this for lower build impact
template <> struct _is_exception_ptr_available<std::exception_ptr>
{
static constexpr bool value = true;
};
} // namespace detail
// std::exception_ptr is an error type
template <> struct is_error_type<std::exception_ptr>
{
static constexpr bool value = true;
};
} // namespace trait
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,364 @@
/* Essentially an internal optional implementation :)
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_VALUE_STORAGE_HPP
#define BOOST_OUTCOME_VALUE_STORAGE_HPP
#include "../config.hpp"
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
namespace detail
{
using status_bitfield_type = uint32_t;
// WARNING: These bits are not tracked by abi-dumper, but changing them will break ABI!
static constexpr status_bitfield_type status_have_value = (1U << 0U);
static constexpr status_bitfield_type status_have_error = (1U << 1U);
static constexpr status_bitfield_type status_have_exception = (1U << 2U);
static constexpr status_bitfield_type status_error_is_errno = (1U << 4U); // can errno be set from this error?
// bit 7 unused
// bits 8-15 unused
// bits 16-31 used for user supplied 16 bit value
static constexpr status_bitfield_type status_2byte_shift = 16;
static constexpr status_bitfield_type status_2byte_mask = (0xffffU << status_2byte_shift);
// Used if T is trivial
template <class T> struct value_storage_trivial
{
using value_type = T;
union {
empty_type _empty;
devoid<T> _value;
};
status_bitfield_type _status{0};
constexpr value_storage_trivial() noexcept : _empty{} {}
// Special from-void catchall constructor, always constructs default T irrespective of whether void is valued or not (can do no better if T cannot be copied)
struct disable_void_catchall
{
};
using void_value_storage_trivial = std::conditional_t<std::is_void<T>::value, disable_void_catchall, value_storage_trivial<void>>;
explicit constexpr value_storage_trivial(const void_value_storage_trivial &o) noexcept(std::is_nothrow_default_constructible<value_type>::value)
: _value()
, _status(o._status)
{
}
value_storage_trivial(const value_storage_trivial &) = default; // NOLINT
value_storage_trivial(value_storage_trivial &&) = default; // NOLINT
value_storage_trivial &operator=(const value_storage_trivial &) = default; // NOLINT
value_storage_trivial &operator=(value_storage_trivial &&) = default; // NOLINT
~value_storage_trivial() = default;
constexpr explicit value_storage_trivial(status_bitfield_type status)
: _empty()
, _status(status)
{
}
template <class... Args>
constexpr explicit value_storage_trivial(in_place_type_t<value_type> /*unused*/, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args...>::value)
: _value(static_cast<Args &&>(args)...)
, _status(status_have_value)
{
}
template <class U, class... Args>
constexpr value_storage_trivial(in_place_type_t<value_type> /*unused*/, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>::value)
: _value(il, static_cast<Args &&>(args)...)
, _status(status_have_value)
{
}
template <class U> static constexpr bool enable_converting_constructor = !std::is_same<std::decay_t<U>, value_type>::value && std::is_constructible<value_type, U>::value;
BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_converting_constructor<U>))
constexpr explicit value_storage_trivial(const value_storage_trivial<U> &o) noexcept(std::is_nothrow_constructible<value_type, U>::value)
: value_storage_trivial(((o._status & status_have_value) != 0) ? value_storage_trivial(in_place_type<value_type>, o._value) : value_storage_trivial()) // NOLINT
{
_status = o._status;
}
BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_converting_constructor<U>))
constexpr explicit value_storage_trivial(value_storage_trivial<U> &&o) noexcept(std::is_nothrow_constructible<value_type, U>::value)
: value_storage_trivial(((o._status & status_have_value) != 0) ? value_storage_trivial(in_place_type<value_type>, static_cast<U &&>(o._value)) : value_storage_trivial()) // NOLINT
{
_status = o._status;
}
constexpr void swap(value_storage_trivial &o) noexcept
{
// storage is trivial, so just use assignment
auto temp = static_cast<value_storage_trivial &&>(*this);
*this = static_cast<value_storage_trivial &&>(o);
o = static_cast<value_storage_trivial &&>(temp);
}
};
// Used if T is non-trivial
template <class T> struct value_storage_nontrivial
{
using value_type = T;
union {
empty_type _empty;
value_type _value;
};
status_bitfield_type _status{0};
value_storage_nontrivial() noexcept : _empty{} {}
value_storage_nontrivial &operator=(const value_storage_nontrivial &) = default; // if reaches here, copy assignment is trivial
value_storage_nontrivial &operator=(value_storage_nontrivial &&) = default; // NOLINT if reaches here, move assignment is trivial
value_storage_nontrivial(value_storage_nontrivial &&o) noexcept(std::is_nothrow_move_constructible<value_type>::value) // NOLINT
: _status(o._status)
{
if(this->_status & status_have_value)
{
this->_status &= ~status_have_value;
new(&_value) value_type(static_cast<value_type &&>(o._value)); // NOLINT
_status = o._status;
}
}
value_storage_nontrivial(const value_storage_nontrivial &o) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
: _status(o._status)
{
if(this->_status & status_have_value)
{
this->_status &= ~status_have_value;
new(&_value) value_type(o._value); // NOLINT
_status = o._status;
}
}
// Special from-void constructor, constructs default T if void valued
explicit value_storage_nontrivial(const value_storage_trivial<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value)
: _status(o._status)
{
if(this->_status & status_have_value)
{
this->_status &= ~status_have_value;
new(&_value) value_type; // NOLINT
_status = o._status;
}
}
explicit value_storage_nontrivial(status_bitfield_type status)
: _empty()
, _status(status)
{
}
template <class... Args>
explicit value_storage_nontrivial(in_place_type_t<value_type> /*unused*/, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args...>::value)
: _value(static_cast<Args &&>(args)...) // NOLINT
, _status(status_have_value)
{
}
template <class U, class... Args>
value_storage_nontrivial(in_place_type_t<value_type> /*unused*/, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>::value)
: _value(il, static_cast<Args &&>(args)...)
, _status(status_have_value)
{
}
template <class U> static constexpr bool enable_converting_constructor = !std::is_same<std::decay_t<U>, value_type>::value && std::is_constructible<value_type, U>::value;
BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_converting_constructor<U>))
constexpr explicit value_storage_nontrivial(const value_storage_nontrivial<U> &o) noexcept(std::is_nothrow_constructible<value_type, U>::value)
: value_storage_nontrivial((o._status & status_have_value) != 0 ? value_storage_nontrivial(in_place_type<value_type>, o._value) : value_storage_nontrivial())
{
_status = o._status;
}
BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_converting_constructor<U>))
constexpr explicit value_storage_nontrivial(const value_storage_trivial<U> &o) noexcept(std::is_nothrow_constructible<value_type, U>::value)
: value_storage_nontrivial((o._status & status_have_value) != 0 ? value_storage_nontrivial(in_place_type<value_type>, o._value) : value_storage_nontrivial())
{
_status = o._status;
}
BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_converting_constructor<U>))
constexpr explicit value_storage_nontrivial(value_storage_nontrivial<U> &&o) noexcept(std::is_nothrow_constructible<value_type, U>::value)
: value_storage_nontrivial((o._status & status_have_value) != 0 ? value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) : value_storage_nontrivial())
{
_status = o._status;
}
BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_converting_constructor<U>))
constexpr explicit value_storage_nontrivial(value_storage_trivial<U> &&o) noexcept(std::is_nothrow_constructible<value_type, U>::value)
: value_storage_nontrivial((o._status & status_have_value) != 0 ? value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) : value_storage_nontrivial())
{
_status = o._status;
}
~value_storage_nontrivial() noexcept(std::is_nothrow_destructible<T>::value)
{
if(this->_status & status_have_value)
{
this->_value.~value_type(); // NOLINT
this->_status &= ~status_have_value;
}
}
constexpr void swap(value_storage_nontrivial &o) noexcept(detail::is_nothrow_swappable<value_type>::value &&std::is_nothrow_move_constructible<value_type>::value)
{
using std::swap;
if((_status & status_have_value) == 0 && (o._status & status_have_value) == 0)
{
swap(_status, o._status);
return;
}
if((_status & status_have_value) != 0 && (o._status & status_have_value) != 0)
{
swap(_value, o._value); // NOLINT
swap(_status, o._status);
return;
}
// One must be empty and the other non-empty, so use move construction
if((_status & status_have_value) != 0)
{
// Move construct me into other
new(&o._value) value_type(static_cast<value_type &&>(_value)); // NOLINT
this->_value.~value_type(); // NOLINT
swap(_status, o._status);
}
else
{
// Move construct other into me
new(&_value) value_type(static_cast<value_type &&>(o._value)); // NOLINT
o._value.~value_type(); // NOLINT
swap(_status, o._status);
}
}
};
template <class Base> struct value_storage_delete_copy_constructor : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
value_storage_delete_copy_constructor() = default;
value_storage_delete_copy_constructor(const value_storage_delete_copy_constructor &) = delete;
value_storage_delete_copy_constructor(value_storage_delete_copy_constructor &&) = default; // NOLINT
};
template <class Base> struct value_storage_delete_copy_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
value_storage_delete_copy_assignment() = default;
value_storage_delete_copy_assignment(const value_storage_delete_copy_assignment &) = default;
value_storage_delete_copy_assignment(value_storage_delete_copy_assignment &&) = default; // NOLINT
value_storage_delete_copy_assignment &operator=(const value_storage_delete_copy_assignment &o) = delete;
value_storage_delete_copy_assignment &operator=(value_storage_delete_copy_assignment &&o) = default; // NOLINT
};
template <class Base> struct value_storage_delete_move_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
value_storage_delete_move_assignment() = default;
value_storage_delete_move_assignment(const value_storage_delete_move_assignment &) = default;
value_storage_delete_move_assignment(value_storage_delete_move_assignment &&) = default; // NOLINT
value_storage_delete_move_assignment &operator=(const value_storage_delete_move_assignment &o) = default;
value_storage_delete_move_assignment &operator=(value_storage_delete_move_assignment &&o) = delete;
};
template <class Base> struct value_storage_delete_move_constructor : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
value_storage_delete_move_constructor() = default;
value_storage_delete_move_constructor(const value_storage_delete_move_constructor &) = default;
value_storage_delete_move_constructor(value_storage_delete_move_constructor &&) = delete;
};
template <class Base> struct value_storage_nontrivial_move_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
value_storage_nontrivial_move_assignment() = default;
value_storage_nontrivial_move_assignment(const value_storage_nontrivial_move_assignment &) = default;
value_storage_nontrivial_move_assignment(value_storage_nontrivial_move_assignment &&) = default; // NOLINT
value_storage_nontrivial_move_assignment &operator=(const value_storage_nontrivial_move_assignment &o) = default;
value_storage_nontrivial_move_assignment &operator=(value_storage_nontrivial_move_assignment &&o) noexcept(std::is_nothrow_move_assignable<value_type>::value) // NOLINT
{
if((this->_status & status_have_value) != 0 && (o._status & status_have_value) != 0)
{
this->_value = static_cast<value_type &&>(o._value); // NOLINT
}
else if((this->_status & status_have_value) != 0 && (o._status & status_have_value) == 0)
{
this->_value.~value_type(); // NOLINT
}
else if((this->_status & status_have_value) == 0 && (o._status & status_have_value) != 0)
{
new(&this->_value) value_type(static_cast<value_type &&>(o._value)); // NOLINT
}
this->_status = o._status;
return *this;
}
};
template <class Base> struct value_storage_nontrivial_copy_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
value_storage_nontrivial_copy_assignment() = default;
value_storage_nontrivial_copy_assignment(const value_storage_nontrivial_copy_assignment &) = default;
value_storage_nontrivial_copy_assignment(value_storage_nontrivial_copy_assignment &&) = default; // NOLINT
value_storage_nontrivial_copy_assignment &operator=(value_storage_nontrivial_copy_assignment &&o) = default; // NOLINT
value_storage_nontrivial_copy_assignment &operator=(const value_storage_nontrivial_copy_assignment &o) noexcept(std::is_nothrow_copy_assignable<value_type>::value)
{
if((this->_status & status_have_value) != 0 && (o._status & status_have_value) != 0)
{
this->_value = o._value; // NOLINT
}
else if((this->_status & status_have_value) != 0 && (o._status & status_have_value) == 0)
{
this->_value.~value_type(); // NOLINT
}
else if((this->_status & status_have_value) == 0 && (o._status & status_have_value) != 0)
{
new(&this->_value) value_type(o._value); // NOLINT
}
this->_status = o._status;
return *this;
}
};
// We don't actually need all of std::is_trivial<>, std::is_trivially_copyable<> is sufficient
template <class T> using value_storage_select_trivality = std::conditional_t<std::is_trivially_copyable<devoid<T>>::value, value_storage_trivial<T>, value_storage_nontrivial<T>>;
template <class T> using value_storage_select_move_constructor = std::conditional_t<std::is_move_constructible<devoid<T>>::value, value_storage_select_trivality<T>, value_storage_delete_move_constructor<value_storage_select_trivality<T>>>;
template <class T> using value_storage_select_copy_constructor = std::conditional_t<std::is_copy_constructible<devoid<T>>::value, value_storage_select_move_constructor<T>, value_storage_delete_copy_constructor<value_storage_select_move_constructor<T>>>;
template <class T>
using value_storage_select_move_assignment = std::conditional_t<std::is_trivially_move_assignable<devoid<T>>::value, value_storage_select_copy_constructor<T>,
std::conditional_t<std::is_move_assignable<devoid<T>>::value, value_storage_nontrivial_move_assignment<value_storage_select_copy_constructor<T>>, value_storage_delete_copy_assignment<value_storage_select_copy_constructor<T>>>>;
template <class T>
using value_storage_select_copy_assignment = std::conditional_t<std::is_trivially_copy_assignable<devoid<T>>::value, value_storage_select_move_assignment<T>,
std::conditional_t<std::is_copy_assignable<devoid<T>>::value, value_storage_nontrivial_copy_assignment<value_storage_select_move_assignment<T>>, value_storage_delete_copy_assignment<value_storage_select_move_assignment<T>>>>;
template <class T> using value_storage_select_impl = value_storage_select_copy_assignment<T>;
#ifndef NDEBUG
// Check is trivial in all ways except default constructibility
// static_assert(std::is_trivial<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivial!");
// static_assert(std::is_trivially_default_constructible<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially default constructible!");
static_assert(std::is_trivially_copyable<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially copyable!");
static_assert(std::is_trivially_assignable<value_storage_select_impl<int>, value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially assignable!");
static_assert(std::is_trivially_destructible<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially destructible!");
static_assert(std::is_trivially_copy_constructible<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially copy constructible!");
static_assert(std::is_trivially_move_constructible<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially move constructible!");
static_assert(std::is_trivially_copy_assignable<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially copy assignable!");
static_assert(std::is_trivially_move_assignable<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not trivially move assignable!");
// Also check is standard layout
static_assert(std::is_standard_layout<value_storage_select_impl<int>>::value, "value_storage_select_impl<int> is not a standard layout type!");
#endif
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,82 @@
/* C interface for result
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Aug 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_EXPERIMENTAL_RESULT_H
#define BOOST_OUTCOME_EXPERIMENTAL_RESULT_H
#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; \
}
#define BOOST_OUTCOME_C_RESULT(ident) struct cxx_result_##ident
#define BOOST_OUTCOME_C_RESULT_HAS_VALUE(r) (((r).flags & 1U) == 1U)
#define BOOST_OUTCOME_C_RESULT_HAS_ERROR(r) (((r).flags & 2U) == 2U)
#define BOOST_OUTCOME_C_RESULT_ERROR_IS_ERRNO(r) (((r).flags & (1U << 4U)) == (1U << 4U))
/***************************** <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_STATUS_CODE(ident) struct cxx_status_code_##ident
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)
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)
#endif

View File

@@ -0,0 +1,240 @@
/* 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_COM_CODE_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_COM_CODE_HPP
#if !defined(_WIN32) && !defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
#error This file should only be included on Windows
#endif
#include "nt_code.hpp"
#include "win32_code.hpp"
#ifndef BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE
#include <comdef.h>
#endif
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
to add semantic equivalence testing for whichever extra COM codes that your application specifically needs.
*/
using com_code = status_code<_com_code_domain>;
//! (Windows only) A specialisation of `status_error` for the COM error 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;
using _base = status_code_domain;
//! Construct from a `HRESULT` error code
static _base::string_ref _make_string_ref(HRESULT c, IErrorInfo *perrinfo = nullptr) noexcept
{
_com_error ce(c, perrinfo);
#ifdef _UNICODE
win32::DWORD wlen = (win32::DWORD) wcslen(ce.ErrorMessage());
size_t allocation = wlen + (wlen >> 1);
win32::DWORD bytes;
if(wlen == 0)
{
return _base::string_ref("failed to get message from system");
}
for(;;)
{
auto *p = static_cast<char *>(malloc(allocation)); // NOLINT
if(p == nullptr)
{
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);
if(bytes != 0)
{
char *end = strchr(p, 0);
while(end[-1] == 10 || end[-1] == 13)
{
--end;
}
*end = 0; // NOLINT
return _base::atomic_refcounted_string_ref(p, end - p);
}
free(p); // NOLINT
if(win32::GetLastError() == 0x7a /*ERROR_INSUFFICIENT_BUFFER*/)
{
allocation += allocation >> 2;
continue;
}
return _base::string_ref("failed to get message from system");
}
#else
auto wlen = static_cast<win32::DWORD>(strlen(ce.ErrorMessage()));
auto *p = static_cast<char *>(malloc(wlen + 1)); // NOLINT
if(p == nullptr)
{
return _base::string_ref("failed to get message from system");
}
memcpy(p, ce.ErrorMessage(), wlen + 1);
char *end = strchr(p, 0);
while(end[-1] == 10 || end[-1] == 13)
{
--end;
}
*end = 0; // NOLINT
return _base::atomic_refcounted_string_ref(p, end - p);
#endif
}
public:
//! The value type of the COM code, which is a `HRESULT`
using value_type = HRESULT;
using _base::string_ref;
public:
//! Default constructor
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;
_com_code_domain &operator=(_com_code_domain &&) = default;
~_com_code_domain() = default;
//! Constexpr singleton getter. Returns the constexpr com_code_domain variable.
static inline constexpr const _com_code_domain &get();
virtual string_ref name() const noexcept override { return string_ref("COM domain"); } // NOLINT
protected:
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
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);
const auto &c1 = static_cast<const com_code &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const com_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
if((c1.value() & FACILITY_NT_BIT) != 0)
{
if(code2.domain() == nt_code_domain)
{
const auto &c2 = static_cast<const nt_code &>(code2); // NOLINT
if(c2.value() == (c1.value() & ~FACILITY_NT_BIT))
{
return true;
}
}
else if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == _nt_code_domain::_nt_code_to_errno(c1.value() & ~FACILITY_NT_BIT))
{
return true;
}
}
}
else if(HRESULT_FACILITY(c1.value()) == FACILITY_WIN32)
{
if(code2.domain() == win32_code_domain)
{
const auto &c2 = static_cast<const win32_code &>(code2); // NOLINT
if(c2.value() == HRESULT_CODE(c1.value()))
{
return true;
}
}
else if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == _win32_code_domain::_win32_code_to_errno(HRESULT_CODE(c1.value())))
{
return true;
}
}
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c1 = static_cast<const com_code &>(code); // NOLINT
if(c1.value() == S_OK)
{
return generic_code(errc::success);
}
if((c1.value() & FACILITY_NT_BIT) != 0)
{
return generic_code(static_cast<errc>(_nt_code_domain::_nt_code_to_errno(c1.value() & ~FACILITY_NT_BIT)));
}
if(HRESULT_FACILITY(c1.value()) == FACILITY_WIN32)
{
return generic_code(static_cast<errc>(_win32_code_domain::_win32_code_to_errno(HRESULT_CODE(c1.value()))));
}
return generic_code(errc::unknown);
}
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const com_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 com_code &>(code); // NOLINT
throw status_error<_com_code_domain>(c);
}
#endif
};
//! (Windows only) A constexpr source variable for the COM code domain. Returned by `_com_code_domain::get()`.
constexpr _com_code_domain com_code_domain;
inline constexpr const _com_code_domain &_com_code_domain::get()
{
return com_code_domain;
}
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,261 @@
/* 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

View File

@@ -0,0 +1,98 @@
case 0x80000002: return EACCES;
case 0x8000000f: return EAGAIN;
case 0x80000010: return EAGAIN;
case 0x80000011: return EBUSY;
case 0xc0000002: return ENOSYS;
case 0xc0000005: return EACCES;
case 0xc0000008: return EINVAL;
case 0xc000000e: return ENOENT;
case 0xc000000f: return ENOENT;
case 0xc0000010: return ENOSYS;
case 0xc0000013: return EAGAIN;
case 0xc0000017: return ENOMEM;
case 0xc000001c: return ENOSYS;
case 0xc000001e: return EACCES;
case 0xc000001f: return EACCES;
case 0xc0000021: return EACCES;
case 0xc0000022: return EACCES;
case 0xc0000024: return EINVAL;
case 0xc0000033: return EINVAL;
case 0xc0000034: return ENOENT;
case 0xc0000035: return EEXIST;
case 0xc0000037: return EINVAL;
case 0xc000003a: return ENOENT;
case 0xc0000040: return ENOMEM;
case 0xc0000041: return EACCES;
case 0xc0000042: return EINVAL;
case 0xc0000043: return EACCES;
case 0xc000004b: return EACCES;
case 0xc0000054: return ENOLCK;
case 0xc0000055: return ENOLCK;
case 0xc0000056: return EACCES;
case 0xc000007f: return ENOSPC;
case 0xc0000087: return ENOMEM;
case 0xc0000097: return ENOMEM;
case 0xc000009b: return ENOENT;
case 0xc000009e: return EAGAIN;
case 0xc00000a2: return EACCES;
case 0xc00000a3: return EAGAIN;
case 0xc00000af: return ENOSYS;
case 0xc00000ba: return EACCES;
case 0xc00000c0: return ENODEV;
case 0xc00000d4: return EXDEV;
case 0xc00000d5: return EACCES;
case 0xc00000fb: return ENOENT;
case 0xc0000101: return ENOTEMPTY;
case 0xc0000103: return EINVAL;
case 0xc0000107: return EBUSY;
case 0xc0000108: return EBUSY;
case 0xc000010a: return EACCES;
case 0xc000011f: return EMFILE;
case 0xc0000120: return ECANCELED;
case 0xc0000121: return EACCES;
case 0xc0000123: return EACCES;
case 0xc0000128: return EINVAL;
case 0xc0000189: return EACCES;
case 0xc00001ad: return ENOMEM;
case 0xc000022d: return EAGAIN;
case 0xc0000235: return EINVAL;
case 0xc000026e: return EAGAIN;
case 0xc000028a: return EACCES;
case 0xc000028b: return EACCES;
case 0xc000028d: return EACCES;
case 0xc000028e: return EACCES;
case 0xc000028f: return EACCES;
case 0xc0000290: return EACCES;
case 0xc000029c: return ENOSYS;
case 0xc00002c5: return EACCES;
case 0xc00002d3: return EAGAIN;
case 0xc00002ea: return EACCES;
case 0xc00002f0: return ENOENT;
case 0xc0000373: return ENOMEM;
case 0xc0000416: return ENOMEM;
case 0xc0000433: return EBUSY;
case 0xc0000434: return EBUSY;
case 0xc0000455: return EINVAL;
case 0xc0000467: return EACCES;
case 0xc0000491: return ENOENT;
case 0xc0000495: return EAGAIN;
case 0xc0000503: return EAGAIN;
case 0xc0000507: return EBUSY;
case 0xc0000512: return EACCES;
case 0xc000070a: return EINVAL;
case 0xc000070b: return EINVAL;
case 0xc000070c: return EINVAL;
case 0xc000070d: return EINVAL;
case 0xc000070e: return EINVAL;
case 0xc000070f: return EINVAL;
case 0xc0000710: return ENOSYS;
case 0xc0000711: return ENOSYS;
case 0xc0000716: return EINVAL;
case 0xc000071b: return ENOSYS;
case 0xc000071d: return ENOSYS;
case 0xc000071e: return ENOSYS;
case 0xc000071f: return ENOSYS;
case 0xc0000720: return ENOSYS;
case 0xc0000721: return ENOSYS;
case 0xc000080f: return EAGAIN;
case 0xc000a203: return EACCES;

View File

@@ -0,0 +1,75 @@
case 0x1: return ENOSYS;
case 0x2: return ENOENT;
case 0x3: return ENOENT;
case 0x4: return EMFILE;
case 0x5: return EACCES;
case 0x6: return EINVAL;
case 0x8: return ENOMEM;
case 0xc: return EACCES;
case 0xe: return ENOMEM;
case 0xf: return ENODEV;
case 0x10: return EACCES;
case 0x11: return EXDEV;
case 0x13: return EACCES;
case 0x14: return ENODEV;
case 0x15: return EAGAIN;
case 0x19: return EIO;
case 0x1d: return EIO;
case 0x1e: return EIO;
case 0x20: return EACCES;
case 0x21: return ENOLCK;
case 0x27: return ENOSPC;
case 0x37: return ENODEV;
case 0x50: return EEXIST;
case 0x52: return EACCES;
case 0x57: return EINVAL;
case 0x6e: return EIO;
case 0x6f: return ENAMETOOLONG;
case 0x70: return ENOSPC;
case 0x7b: return EINVAL;
case 0x83: return EINVAL;
case 0x8e: return EBUSY;
case 0x91: return ENOTEMPTY;
case 0xaa: return EBUSY;
case 0xb7: return EEXIST;
case 0xd4: return ENOLCK;
case 0x10b: return EINVAL;
case 0x3e3: return ECANCELED;
case 0x3e6: return EACCES;
case 0x3f3: return EIO;
case 0x3f4: return EIO;
case 0x3f5: return EIO;
case 0x4d5: return EAGAIN;
case 0x961: return EBUSY;
case 0x964: return EBUSY;
case 0x2714: return EINTR;
case 0x2719: return EBADF;
case 0x271d: return EACCES;
case 0x271e: return EFAULT;
case 0x2726: return EINVAL;
case 0x2728: return EMFILE;
case 0x2733: return EWOULDBLOCK;
case 0x2734: return EINPROGRESS;
case 0x2735: return EALREADY;
case 0x2736: return ENOTSOCK;
case 0x2737: return EDESTADDRREQ;
case 0x2738: return EMSGSIZE;
case 0x2739: return EPROTOTYPE;
case 0x273a: return ENOPROTOOPT;
case 0x273b: return EPROTONOSUPPORT;
case 0x273d: return EOPNOTSUPP;
case 0x273f: return EAFNOSUPPORT;
case 0x2740: return EADDRINUSE;
case 0x2741: return EADDRNOTAVAIL;
case 0x2742: return ENETDOWN;
case 0x2743: return ENETUNREACH;
case 0x2744: return ENETRESET;
case 0x2745: return ECONNABORTED;
case 0x2746: return ECONNRESET;
case 0x2747: return ENOBUFS;
case 0x2748: return EISCONN;
case 0x2749: return ENOTCONN;
case 0x274c: return ETIMEDOUT;
case 0x274d: return ECONNREFUSED;
case 0x274f: return ENAMETOOLONG;
case 0x2751: return EHOSTUNREACH;

View File

@@ -0,0 +1,65 @@
/* 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_ERROR_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_ERROR_HPP
#include "errored_status_code.hpp"
#include "system_code.hpp"
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! An erased `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
[P0709 Zero-overhead deterministic exceptions](https://wg21.link/P0709).
Differences from `system_code`:
- Always a failure (this is checked at construction, and if not the case,
the program is terminated as this is a logic error)
- No default construction.
- No empty state possible.
- Is immutable.
As with `system_code`, it remains guaranteed to be two CPU registers in size,
and move relocating.
*/
using error = errored_status_code<erased<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!");
#endif
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,342 @@
/* 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

View File

@@ -0,0 +1,378 @@
/* 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

View File

@@ -0,0 +1,78 @@
/* 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_IOSTREAM_SUPPORT_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_IOSTREAM_SUPPORT_HPP
#include "error.hpp"
#include <iostream>
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>
inline std::ostream &operator<<(std::ostream &s, const status_code<DomainType> &v)
{
if(v.empty())
{
return s << "(empty)";
}
return s << v.domain().name().c_str() << ": " << v.value();
}
/*! 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)
{
if(v.empty())
{
return s << "(empty)";
}
return s << v.domain().name().c_str() << ": " << v.message().c_str();
}
/*! 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();
}
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,212 @@
/* 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_NT_CODE_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_NT_CODE_HPP
#if !defined(_WIN32) && !defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
#error This file should only be included on Windows
#endif
#include "win32_code.hpp"
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
//! \exclude
namespace win32
{
// A Win32 NTSTATUS
using NTSTATUS = long;
// 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);
}
class _nt_code_domain;
//! (Windows only) A NT error code, those returned by NT kernel functions.
using nt_code = status_code<_nt_code_domain>;
//! (Windows only) A specialisation of `status_error` for the NT error 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;
friend class _com_code_domain;
using _base = status_code_domain;
static int _nt_code_to_errno(win32::NTSTATUS c)
{
if(c >= 0)
{
return 0; // success
}
switch(static_cast<unsigned>(c))
{
#include "detail/nt_code_to_generic_code.ipp"
}
return -1;
}
static win32::DWORD _nt_code_to_win32_code(win32::NTSTATUS c) // NOLINT
{
if(c >= 0)
{
return 0; // success
}
switch(static_cast<unsigned>(c))
{
#include "detail/nt_code_to_win32_code.ipp"
}
return static_cast<win32::DWORD>(-1);
}
//! Construct from a NT error code
static _base::string_ref _make_string_ref(win32::NTSTATUS c) noexcept
{
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);
size_t allocation = wlen + (wlen >> 1);
win32::DWORD bytes;
if(wlen == 0)
{
return _base::string_ref("failed to get message from system");
}
for(;;)
{
auto *p = static_cast<char *>(malloc(allocation)); // NOLINT
if(p == nullptr)
{
return _base::string_ref("failed to get message from system");
}
bytes = win32::WideCharToMultiByte(65001 /*CP_UTF8*/, 0, buffer, (int) (wlen + 1), p, (int) allocation, nullptr, nullptr);
if(bytes != 0)
{
char *end = strchr(p, 0);
while(end[-1] == 10 || end[-1] == 13)
{
--end;
}
*end = 0; // NOLINT
return _base::atomic_refcounted_string_ref(p, end - p);
}
free(p); // NOLINT
if(win32::GetLastError() == 0x7a /*ERROR_INSUFFICIENT_BUFFER*/)
{
allocation += allocation >> 2;
continue;
}
return _base::string_ref("failed to get message from system");
}
}
public:
//! The value type of the NT code, which is a `win32::NTSTATUS`
using value_type = win32::NTSTATUS;
using _base::string_ref;
public:
//! Default constructor
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;
_nt_code_domain &operator=(_nt_code_domain &&) = default;
~_nt_code_domain() = default;
//! Constexpr singleton getter. Returns the constexpr nt_code_domain variable.
static inline constexpr const _nt_code_domain &get();
virtual string_ref name() const noexcept override { return string_ref("NT domain"); } // NOLINT
protected:
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
return static_cast<const nt_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);
const auto &c1 = static_cast<const nt_code &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const nt_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == _nt_code_to_errno(c1.value()))
{
return true;
}
}
if(code2.domain() == win32_code_domain)
{
const auto &c2 = static_cast<const win32_code &>(code2); // NOLINT
if(c2.value() == _nt_code_to_win32_code(c1.value()))
{
return true;
}
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const nt_code &>(code); // NOLINT
return generic_code(static_cast<errc>(_nt_code_to_errno(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 nt_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 nt_code &>(code); // NOLINT
throw status_error<_nt_code_domain>(c);
}
#endif
};
//! (Windows only) A constexpr source variable for the NT code domain, which is that of NT kernel functions. Returned by `_nt_code_domain::get()`.
constexpr _nt_code_domain nt_code_domain;
inline constexpr const _nt_code_domain &_nt_code_domain::get()
{
return nt_code_domain;
}
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,151 @@
/* 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_POSIX_CODE_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_POSIX_CODE_HPP
#include "generic_code.hpp"
#include <cstring> // for strchr and strerror_r
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
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>;
/*! 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;
using _base = status_code_domain;
static _base::string_ref _make_string_ref(int c) noexcept
{
char buffer[1024] = "";
#ifdef _WIN32
strerror_s(buffer, sizeof(buffer), c);
#elif defined(__linux__)
char *s = strerror_r(c, buffer, sizeof(buffer)); // NOLINT
if(s != nullptr)
{
strncpy(buffer, s, sizeof(buffer)); // NOLINT
buffer[1023] = 0;
}
#else
strerror_r(c, buffer, sizeof(buffer));
#endif
size_t length = strlen(buffer); // NOLINT
auto *p = static_cast<char *>(malloc(length + 1)); // NOLINT
if(p == nullptr)
{
return _base::string_ref("failed to get message from system");
}
memcpy(p, buffer, length + 1); // NOLINT
return _base::atomic_refcounted_string_ref(p, length);
}
public:
//! The value type of the POSIX code, which is an `int`
using value_type = int;
using _base::string_ref;
//! Default constructor
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;
_posix_code_domain &operator=(_posix_code_domain &&) = default;
~_posix_code_domain() = default;
//! Constexpr singleton getter. Returns constexpr posix_code_domain variable.
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
{
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
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const posix_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == c1.value())
{
return true;
}
}
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 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
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
throw status_error<_posix_code_domain>(c);
}
#endif
};
//! A constexpr source variable for the POSIX code domain, which is that of `errno`. Returned by `_posix_code_domain::get()`.
constexpr _posix_code_domain posix_code_domain;
inline constexpr const _posix_code_domain &_posix_code_domain::get()
{
return posix_code_domain;
}
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,502 @@
/* 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

View File

@@ -0,0 +1,365 @@
/* 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_DOMAIN_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_CODE_DOMAIN_HPP
#include "config.hpp"
#include <cstring> // for strchr
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>>`).
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
surprise on this, `operator<` and `std::hash<>` are NOT implemented in order to
trap potential incorrectness. Define your own custom comparison functions for your
container which perform exact comparisons.
*/
template <class DomainType> class status_code;
class _generic_code_domain;
//! The generic code is a status code with the generic code domain, which is that of `errc` (POSIX).
using generic_code = status_code<_generic_code_domain>;
namespace detail
{
template <class StatusCode> class indirecting_domain;
template <class T> struct status_code_sizer
{
void *a;
T b;
};
template <class To, class From> struct type_erasure_is_safe
{
static constexpr bool value = traits::is_move_relocating<From>::value //
&& (sizeof(status_code_sizer<From>) <= sizeof(status_code_sizer<To>));
};
} // namespace detail
/*! Abstract base class for a coding domain of a status code.
*/
class status_code_domain
{
template <class DomainType> friend class status_code;
template <class StatusCode> friend class indirecting_domain;
public:
//! Type of the unique id for this domain.
using unique_id_type = unsigned long long;
/*! (Potentially thread safe) Reference to a message string.
Be aware that you cannot add payload to implementations of this class.
You get exactly the `void *[3]` array to keep state, this is usually
sufficient for a `std::shared_ptr<>` or a `std::string`.
You can install a handler to be called when this object is copied,
moved and destructed. This takes the form of a C function pointer.
*/
class string_ref
{
public:
//! The value type
using value_type = const char;
//! The size type
using size_type = size_t;
//! The pointer type
using pointer = const char *;
//! The const pointer type
using const_pointer = const char *;
//! The iterator type
using iterator = const char *;
//! The const iterator type
using const_iterator = const char *;
protected:
//! The operation occurring
enum class _thunk_op
{
copy,
move,
destruct
};
//! The prototype of the handler function. Copies can throw, moves and destructs cannot.
using _thunk_spec = void (*)(string_ref *dest, const string_ref *src, _thunk_op op);
#ifndef NDEBUG
private:
static void _checking_string_thunk(string_ref *dest, const string_ref *src, _thunk_op /*unused*/) noexcept
{
(void) dest;
(void) src;
assert(dest->_thunk == _checking_string_thunk); // NOLINT
assert(src == nullptr || src->_thunk == _checking_string_thunk); // NOLINT
// do nothing
}
protected:
#endif
//! Pointers to beginning and end of character range
pointer _begin{}, _end{};
//! Three `void*` of state
void *_state[3]{}; // at least the size of a shared_ptr
//! Handler for when operations occur
const _thunk_spec _thunk{nullptr};
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,
#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)
{
}
//! Copy construct the derived implementation.
string_ref(const string_ref &o)
: _begin(o._begin)
, _end(o._end)
, _state{o._state[0], o._state[1], o._state[2]}
, _thunk(o._thunk)
{
if(_thunk != nullptr)
{
_thunk(this, &o, _thunk_op::copy);
}
}
//! 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)
{
if(_thunk != nullptr)
{
_thunk(this, &o, _thunk_op::move);
}
}
//! Copy assignment
string_ref &operator=(const string_ref &o)
{
if(this != &o)
{
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
string_ref temp(static_cast<string_ref &&>(*this));
this->~string_ref();
try
{
new(this) string_ref(o); // may throw
}
catch(...)
{
new(this) string_ref(static_cast<string_ref &&>(temp));
throw;
}
#else
this->~string_ref();
new(this) string_ref(o);
#endif
}
return *this;
}
//! Move assignment
string_ref &operator=(string_ref &&o) noexcept
{
if(this != &o)
{
this->~string_ref();
new(this) string_ref(static_cast<string_ref &&>(o));
}
return *this;
}
//! Destruction
~string_ref()
{
if(_thunk != nullptr)
{
_thunk(this, nullptr, _thunk_op::destruct);
}
_begin = _end = nullptr;
}
//! Returns whether the reference is empty or not
BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD bool empty() const noexcept { return _begin == _end; }
//! Returns the size of the string
size_type size() const noexcept { return _end - _begin; }
//! Returns a null terminated C string
const_pointer c_str() const noexcept { return _begin; }
//! Returns a null terminated C string
const_pointer data() const noexcept { return _begin; }
//! Returns the beginning of the string
iterator begin() noexcept { return _begin; }
//! Returns the beginning of the string
const_iterator begin() const noexcept { return _begin; }
//! Returns the beginning of the string
const_iterator cbegin() const noexcept { return _begin; }
//! Returns the end of the string
iterator end() noexcept { return _end; }
//! Returns the end of the string
const_iterator end() const noexcept { return _end; }
//! Returns the end of the string
const_iterator cend() const noexcept { return _end; }
};
/*! A reference counted, threadsafe reference to a message string.
*/
class atomic_refcounted_string_ref : public string_ref
{
struct _allocated_msg
{
mutable std::atomic<unsigned> count{1};
};
_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
{
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
switch(op)
{
case _thunk_op::copy:
{
if(dest->_msg() != nullptr)
{
auto count = dest->_msg()->count.fetch_add(1, std::memory_order_relaxed);
(void) count;
assert(count != 0); // NOLINT
}
return;
}
case _thunk_op::move:
{
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;
return;
}
case _thunk_op::destruct:
{
if(dest->_msg() != nullptr)
{
auto count = dest->_msg()->count.fetch_sub(1, std::memory_order_release);
if(count == 1)
{
std::atomic_thread_fence(std::memory_order_acquire);
free((void *) dest->_begin); // NOLINT
delete dest->_msg(); // NOLINT
}
}
}
}
}
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)
{
if(_msg() == nullptr)
{
free((void *) this->_begin); // NOLINT
_msg() = nullptr; // disabled
this->_begin = "failed to get message from system";
this->_end = strchr(this->_begin, 0);
return;
}
}
};
private:
unique_id_type _id;
protected:
/*! Use [https://www.random.org/cgi-bin/randbyte?nbytes=8&format=h](https://www.random.org/cgi-bin/randbyte?nbytes=8&format=h) to get a random 64 bit id.
Do NOT make up your own value. Do NOT use zero.
*/
constexpr explicit status_code_domain(unique_id_type id) noexcept : _id(id) {}
//! No public copying at type erased level
status_code_domain(const status_code_domain &) = default;
//! No public moving at type erased level
status_code_domain(status_code_domain &&) = default;
//! No public assignment at type erased level
status_code_domain &operator=(const status_code_domain &) = default;
//! No public assignment at type erased level
status_code_domain &operator=(status_code_domain &&) = default;
//! No public destruction at type erased level
~status_code_domain() = default;
public:
//! True if the unique ids match.
constexpr bool operator==(const status_code_domain &o) const noexcept { return _id == o._id; }
//! True if the unique ids do not match.
constexpr bool operator!=(const status_code_domain &o) const noexcept { return _id != o._id; }
//! True if this unique is lower than the other's unique id.
constexpr bool operator<(const status_code_domain &o) const noexcept { return _id < o._id; }
//! 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;
protected:
//! True if code means failure.
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;
//! Returns the generic code closest to this code, if any.
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;
#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;
#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, destroy the erased value type. Default implementation does nothing.
virtual void _do_erased_destroy(status_code<void> &code, size_t bytes) const noexcept // NOLINT
{
(void) code;
(void) bytes;
}
};
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,137 @@
/* 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

View File

@@ -0,0 +1,104 @@
/* 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

View File

@@ -0,0 +1,184 @@
/* 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

View File

@@ -0,0 +1,66 @@
/* 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_SYSTEM_CODE_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_SYSTEM_CODE_HPP
#include "posix_code.hpp"
#if defined(_WIN32) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
#include "nt_code.hpp"
#include "win32_code.hpp"
// NOT "com_code.hpp"
#endif
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! An erased-mutable status code suitably large for all the system codes
which can be returned on this system.
For Windows, these might be:
- `com_code` (`HRESULT`) [you need to include "com_code.hpp" explicitly for this]
- `nt_code` (`LONG`)
- `win32_code` (`DWORD`)
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>>;
#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!");
#endif
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,126 @@
/* Proposed SG14 status_code
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: June 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_SYSTEM_CODE_FROM_EXCEPTION_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_SYSTEM_CODE_FROM_EXCEPTION_HPP
#include "system_code.hpp"
#include <exception> // for exception_ptr
#include <stdexcept> // for the exception types
#include <system_error> // for std::system_error
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! A utility function which returns the closest matching system_code to a supplied
exception ptr.
*/
inline system_code system_code_from_exception(std::exception_ptr &&ep = std::current_exception(), system_code not_matched = generic_code(errc::resource_unavailable_try_again)) noexcept
{
if(!ep)
{
return generic_code(errc::success);
}
try
{
std::rethrow_exception(ep);
}
catch(const std::invalid_argument & /*unused*/)
{
ep = std::exception_ptr();
return generic_code(errc::invalid_argument);
}
catch(const std::domain_error & /*unused*/)
{
ep = std::exception_ptr();
return generic_code(errc::argument_out_of_domain);
}
catch(const std::length_error & /*unused*/)
{
ep = std::exception_ptr();
return generic_code(errc::argument_list_too_long);
}
catch(const std::out_of_range & /*unused*/)
{
ep = std::exception_ptr();
return generic_code(errc::result_out_of_range);
}
catch(const std::logic_error & /*unused*/) /* base class for this group */
{
ep = std::exception_ptr();
return generic_code(errc::invalid_argument);
}
catch(const std::system_error &e) /* also catches ios::failure */
{
ep = std::exception_ptr();
if(e.code().category() == std::generic_category())
{
return generic_code(static_cast<errc>(static_cast<int>(e.code().value())));
}
if(e.code().category() == std::system_category())
{
#ifdef _WIN32
return win32_code(e.code().value());
#else
return posix_code(e.code().value());
#endif
}
// Don't know this error code category, can't wrap it into std_error_code
// as its payload won't fit into system_code, so fall through.
}
catch(const std::overflow_error & /*unused*/)
{
ep = std::exception_ptr();
return generic_code(errc::value_too_large);
}
catch(const std::range_error & /*unused*/)
{
ep = std::exception_ptr();
return generic_code(errc::result_out_of_range);
}
catch(const std::runtime_error & /*unused*/) /* base class for this group */
{
ep = std::exception_ptr();
return generic_code(errc::resource_unavailable_try_again);
}
catch(const std::bad_alloc & /*unused*/)
{
ep = std::exception_ptr();
return generic_code(errc::not_enough_memory);
}
catch(...)
{
}
return not_matched;
}
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,36 @@
/* 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_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_HPP
#include "error.hpp"
#endif

View File

@@ -0,0 +1,193 @@
/* 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_WIN32_CODE_HPP
#define BOOST_OUTCOME_SYSTEM_ERROR2_WIN32_CODE_HPP
#if !defined(_WIN32) && !defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
#error This file should only be included on Windows
#endif
#include "generic_code.hpp"
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
//! \exclude
namespace win32
{
// A Win32 DWORD
using DWORD = unsigned long;
// Used to retrieve the current Win32 error code
extern "C" 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);
// 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);
#pragma comment(lib, "kernel32.lib")
} // namespace win32
class _win32_code_domain;
class _com_code_domain;
//! (Windows only) A Win32 error code, those returned by `GetLastError()`.
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>;
/*! (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;
friend class _com_code_domain;
using _base = status_code_domain;
static int _win32_code_to_errno(win32::DWORD c)
{
switch(c)
{
case 0:
return 0;
#include "detail/win32_code_to_generic_code.ipp"
}
return -1;
}
//! Construct from a Win32 error code
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);
size_t allocation = wlen + (wlen >> 1);
win32::DWORD bytes;
if(wlen == 0)
{
return _base::string_ref("failed to get message from system");
}
for(;;)
{
auto *p = static_cast<char *>(malloc(allocation)); // NOLINT
if(p == nullptr)
{
return _base::string_ref("failed to get message from system");
}
bytes = win32::WideCharToMultiByte(65001 /*CP_UTF8*/, 0, buffer, (int) (wlen + 1), p, (int) allocation, nullptr, nullptr);
if(bytes != 0)
{
char *end = strchr(p, 0);
while(end[-1] == 10 || end[-1] == 13)
{
--end;
}
*end = 0; // NOLINT
return _base::atomic_refcounted_string_ref(p, end - p);
}
free(p); // NOLINT
if(win32::GetLastError() == 0x7a /*ERROR_INSUFFICIENT_BUFFER*/)
{
allocation += allocation >> 2;
continue;
}
return _base::string_ref("failed to get message from system");
}
}
public:
//! The value type of the win32 code, which is a `win32::DWORD`
using value_type = win32::DWORD;
using _base::string_ref;
public:
//! Default constructor
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;
_win32_code_domain &operator=(_win32_code_domain &&) = default;
~_win32_code_domain() = default;
//! Constexpr singleton getter. Returns the constexpr win32_code_domain variable.
static inline constexpr const _win32_code_domain &get();
virtual string_ref name() const noexcept override { return string_ref("win32 domain"); } // NOLINT
protected:
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
return static_cast<const win32_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);
const auto &c1 = static_cast<const win32_code &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const win32_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == _win32_code_to_errno(c1.value()))
{
return true;
}
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const win32_code &>(code); // NOLINT
return generic_code(static_cast<errc>(_win32_code_to_errno(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 win32_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 win32_code &>(code); // NOLINT
throw status_error<_win32_code_domain>(c);
}
#endif
};
//! (Windows only) A constexpr source variable for the win32 code domain, which is that of `GetLastError()` (Windows). Returned by `_win32_code_domain::get()`.
constexpr _win32_code_domain win32_code_domain;
inline constexpr const _win32_code_domain &_win32_code_domain::get()
{
return win32_code_domain;
}
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,149 @@
/* A less simple result type
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Apr 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_EXPERIMENTAL_STATUS_OUTCOME_HPP
#define BOOST_OUTCOME_EXPERIMENTAL_STATUS_OUTCOME_HPP
#include "../basic_outcome.hpp"
#include "../detail/trait_std_exception.hpp"
#include "status_result.hpp"
#include "boost/exception_ptr.hpp"
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
template <class DomainType> inline std::exception_ptr basic_outcome_failure_exception_from_error(const status_code<DomainType> &sc)
{
(void) sc;
#ifndef BOOST_NO_EXCEPTIONS
try
{
sc.throw_exception();
}
catch(...)
{
return std::current_exception();
}
#endif
return {};
}
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 //
>>;
} // namespace policy
/*! 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>> //
using status_outcome = basic_outcome<R, S, P, NoValuePolicy>;
namespace policy
{
template <class T, class DomainType, class E> struct status_code_throw<T, status_code<DomainType>, E> : base
{
using _base = base;
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(static_cast<Impl &&>(self)))
{
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
}
if(base::_has_error(static_cast<Impl &&>(self)))
{
#ifndef BOOST_NO_EXCEPTIONS
base::_error(static_cast<Impl &&>(self)).throw_exception();
#else
BOOST_OUTCOME_THROW_EXCEPTION("wide value check failed");
#endif
}
}
}
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>
{
status_code_throw() = default;
using status_code_throw<T, status_code<DomainType>, E>::status_code_throw;
};
} // namespace policy
} // namespace experimental
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,108 @@
/* A very simple result type
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Apr 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_EXPERIMENTAL_STATUS_RESULT_HPP
#define BOOST_OUTCOME_EXPERIMENTAL_STATUS_RESULT_HPP
#include "../basic_result.hpp"
#include "../policy/fail_to_compile_observers.hpp"
#include "status-code/system_error2.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
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; }
} // namespace detail
namespace experimental
{
using namespace BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE;
using BOOST_OUTCOME_V2_NAMESPACE::success;
using BOOST_OUTCOME_V2_NAMESPACE::failure;
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>?");
};
template <class T, class DomainType> struct status_code_throw<T, status_code<DomainType>, void> : base
{
using _base = base;
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(static_cast<Impl &&>(self)))
{
if(base::_has_error(static_cast<Impl &&>(self)))
{
#ifndef BOOST_NO_EXCEPTIONS
base::_error(static_cast<Impl &&>(self)).throw_exception();
#else
BOOST_OUTCOME_THROW_EXCEPTION("wide value check failed");
#endif
}
}
}
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>
{
status_code_throw() = default;
using status_code_throw<T, status_code<DomainType>, void>::status_code_throw;
};
template <class T, class EC>
using default_status_result_policy = std::conditional_t< //
std::is_void<EC>::value, //
BOOST_OUTCOME_V2_NAMESPACE::policy::terminate, //
std::conditional_t<is_status_code<EC>::value || is_errored_status_code<EC>::value, //
status_code_throw<T, EC, void>, //
BOOST_OUTCOME_V2_NAMESPACE::policy::fail_to_compile_observers //
>>;
} // namespace policy
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S = system_code, class NoValuePolicy = policy::default_status_result_policy<R, S>> //
using status_result = basic_result<R, S, NoValuePolicy>;
} // namespace experimental
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,276 @@
/* iostream specialisations for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: July 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_IOSTREAM_SUPPORT_HPP
#define BOOST_OUTCOME_IOSTREAM_SUPPORT_HPP
#include "outcome.hpp"
#include <iostream>
#include <sstream>
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
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)
{
s << v._status << " ";
if((v._status & status_have_value) != 0)
{
s << v._value; // NOLINT
}
return s;
}
inline std::ostream &operator<<(std::ostream &s, const value_storage_trivial<void> &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)
{
s << v._value; // NOLINT
}
return s;
}
template <class T> inline std::istream &operator>>(std::istream &s, value_storage_trivial<T> &v)
{
v = value_storage_trivial<T>();
s >> v._status;
if((v._status & status_have_value) != 0)
{
new(&v._value) decltype(v._value)(); // NOLINT
s >> v._value; // NOLINT
}
return s;
}
inline std::istream &operator>>(std::istream &s, value_storage_trivial<devoid<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)
{
new(&v._value) decltype(v._value)(); // NOLINT
s >> v._value; // NOLINT
}
return s;
}
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 {}; }
inline std::string safe_message(const std::error_code &ec) { return " (" + ec.message() + ")"; }
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class R, class S, class P)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(detail::lvalueref<std::istream>() >> detail::lvalueref<R>()), BOOST_OUTCOME_TEXPR(detail::lvalueref<std::istream>() >> detail::lvalueref<S>()))
inline std::istream &operator>>(std::istream &s, basic_result<R, S, P> &v)
{
s >> v._iostreams_state();
if(v.has_error())
{
s >> v.assume_error();
}
return s;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class R, class S, class P)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(detail::lvalueref<std::ostream>() << detail::lvalueref<R>()), BOOST_OUTCOME_TEXPR(detail::lvalueref<std::ostream>() << detail::lvalueref<S>()))
inline std::ostream &operator<<(std::ostream &s, const basic_result<R, S, P> &v)
{
s << v._iostreams_state();
if(v.has_error())
{
s << v.assume_error();
}
return s;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class P> inline std::string print(const basic_result<R, S, P> &v)
{
std::stringstream s;
if(v.has_value())
{
s << v.value();
}
if(v.has_error())
{
s << v.error() << detail::safe_message(v.error());
}
return s.str();
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class S, class P> inline std::string print(const basic_result<void, S, P> &v)
{
std::stringstream s;
if(v.has_value())
{
s << "(+void)";
}
if(v.has_error())
{
s << v.error() << detail::safe_message(v.error());
}
return s.str();
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class P> inline std::string print(const basic_result<R, void, P> &v)
{
std::stringstream s;
if(v.has_value())
{
s << v.value();
}
if(v.has_error())
{
s << "(-void)";
}
return s.str();
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class P> inline std::string print(const basic_result<void, void, P> &v)
{
std::stringstream s;
if(v.has_value())
{
s << "(+void)";
}
if(v.has_error())
{
s << "(-void)";
}
return s.str();
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class R, class S, class P, class N)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(detail::lvalueref<std::istream>() >> detail::lvalueref<R>()), BOOST_OUTCOME_TEXPR(detail::lvalueref<std::istream>() >> detail::lvalueref<S>()), BOOST_OUTCOME_TEXPR(detail::lvalueref<std::istream>() >> detail::lvalueref<P>()))
inline std::istream &operator>>(std::istream &s, outcome<R, S, P, N> &v)
{
s >> v._iostreams_state();
if(v.has_error())
{
s >> v.assume_error();
}
if(v.has_exception())
{
s >> v.assume_exception();
}
return s;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class R, class S, class P, class N)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(detail::lvalueref<std::ostream>() << detail::lvalueref<R>()), BOOST_OUTCOME_TEXPR(detail::lvalueref<std::ostream>() << detail::lvalueref<S>()), BOOST_OUTCOME_TEXPR(detail::lvalueref<std::ostream>() << detail::lvalueref<P>()))
inline std::ostream &operator<<(std::ostream &s, const outcome<R, S, P, N> &v)
{
s << v._iostreams_state();
if(v.has_error())
{
s << v.assume_error();
}
if(v.has_exception())
{
s << v.assume_exception();
}
return s;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class P, class N> inline std::string print(const outcome<R, S, P, N> &v)
{
std::stringstream s;
int total = static_cast<int>(v.has_value()) + static_cast<int>(v.has_error()) + static_cast<int>(v.has_exception());
if(total > 1)
{
s << "{ ";
}
s << print(static_cast<const basic_result<R, S, N> &>(static_cast<const detail::basic_result_final<R, S, N> &>(v))); // NOLINT
if(total > 1)
{
s << ", ";
}
if(v.has_exception())
{
#ifndef BOOST_NO_EXCEPTIONS
try
{
rethrow_exception(v.exception());
}
catch(const std::system_error &e)
{
s << "std::system_error code " << e.code() << ": " << e.what();
}
catch(const std::exception &e)
{
s << "std::exception: " << e.what();
}
catch(...)
#endif
{
s << "unknown exception";
}
}
if(total > 1)
{
s << " }";
}
return s.str();
}
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,46 @@
/* A less simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_OUTCOME_HPP
#define BOOST_OUTCOME_OUTCOME_HPP
#include "result.hpp"
#include "boost_outcome.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
/*! In standalone Outcome, this aliases `std_outcome<>`. In Boost.Outcome, this aliases `boost_outcome<>`.
*/
template <class R, class S = boost::system::error_code, class P = boost::exception_ptr, class NoValuePolicy = policy::default_policy<R, S, P>> //
using outcome = boost_outcome<R, S, P, NoValuePolicy>;
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,53 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_ALL_NARROW_HPP
#define BOOST_OUTCOME_POLICY_ALL_NARROW_HPP
#include "base.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition all_narrow. Potential doc page: `all_narrow`
*/
struct all_narrow : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self) { base::narrow_value_check(static_cast<Impl &&>(self)); }
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)); }
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,107 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_BASE_HPP
#define BOOST_OUTCOME_POLICY_BASE_HPP
#include "../config.hpp"
#include <cassert>
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
struct base
{
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 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 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; }
public:
template <class R, class S, class P, class NoValuePolicy, class Impl> static inline constexpr auto &&_exception(Impl &&self) noexcept;
template <class Impl> static constexpr void narrow_value_check(Impl &&self) noexcept
{
if(!_has_value(self))
{
_ub(self);
}
}
template <class Impl> static constexpr void narrow_error_check(Impl &&self) noexcept
{
if(!_has_error(self))
{
_ub(self);
}
}
template <class Impl> static constexpr void narrow_exception_check(Impl &&self) noexcept
{
if(!_has_exception(self))
{
_ub(self);
}
}
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,60 @@
/* Policies for result and outcome
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 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_POLICY_FAIL_TO_COMPILE_OBSERVERS_HPP
#define BOOST_OUTCOME_POLICY_FAIL_TO_COMPILE_OBSERVERS_HPP
#include "base.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
#define BOOST_OUTCOME_FAIL_TO_COMPILE_OBSERVERS_MESSAGE \
"Attempt to wide observe value, error or " \
"exception for a basic_result/basic_outcome given an EC or EP type which is not void, and for whom " \
"trait::is_error_code_available<EC>, trait::is_exception_ptr_available<EC>, and trait::is_exception_ptr_available<EP> " \
"are all false. Please specify a NoValuePolicy to tell basic_result/basic_outcome what to do, or else use " \
"a more specific convenience type alias such as unchecked<T, E> to indicate you want the wide " \
"observers to be narrow, or checked<T, E> to indicate you always want an exception throw etc."
namespace policy
{
struct fail_to_compile_observers : base
{
template <class Impl> static constexpr void wide_value_check(Impl && /* unused */) { static_assert(!std::is_same<Impl, Impl>::value, BOOST_OUTCOME_FAIL_TO_COMPILE_OBSERVERS_MESSAGE); }
template <class Impl> static constexpr void wide_error_check(Impl && /* unused */) { static_assert(!std::is_same<Impl, Impl>::value, BOOST_OUTCOME_FAIL_TO_COMPILE_OBSERVERS_MESSAGE); }
template <class Impl> static constexpr void wide_exception_check(Impl && /* unused */) { static_assert(!std::is_same<Impl, Impl>::value, BOOST_OUTCOME_FAIL_TO_COMPILE_OBSERVERS_MESSAGE); }
};
} // namespace policy
#undef BOOST_OUTCOME_FAIL_TO_COMPILE_OBSERVERS_MESSAGE
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,80 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_OUTCOME_ERROR_CODE_THROW_AS_SYSTEM_ERROR_HPP
#define BOOST_OUTCOME_POLICY_OUTCOME_ERROR_CODE_THROW_AS_SYSTEM_ERROR_HPP
#include "result_error_code_throw_as_system_error.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition error_code_throw_as_system_error. Potential doc page: NOT FOUND
*/
template <class T, class EC, class E> struct error_code_throw_as_system_error : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(std::forward<Impl>(self)))
{
if(base::_has_exception(std::forward<Impl>(self)))
{
detail::_rethrow_exception<trait::is_exception_ptr_available<E>::value>{base::_exception<T, EC, E, error_code_throw_as_system_error>(std::forward<Impl>(self))}; // NOLINT
}
if(base::_has_error(std::forward<Impl>(self)))
{
// ADL discovered
outcome_throw_as_system_error_with_payload(base::_error(std::forward<Impl>(self)));
}
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no value")); // NOLINT
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self)
{
if(!base::_has_error(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no error")); // NOLINT
}
}
template <class Impl> static constexpr void wide_exception_check(Impl &&self)
{
if(!base::_has_exception(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no exception")); // NOLINT
}
}
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,79 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_OUTCOME_EXCEPTION_PTR_RETHROW_HPP
#define BOOST_OUTCOME_POLICY_OUTCOME_EXCEPTION_PTR_RETHROW_HPP
#include "result_exception_ptr_rethrow.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition exception_ptr_rethrow. Potential doc page: NOT FOUND
*/
template <class T, class EC, class E> struct exception_ptr_rethrow : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(std::forward<Impl>(self)))
{
if(base::_has_exception(std::forward<Impl>(self)))
{
detail::_rethrow_exception<trait::is_exception_ptr_available<E>::value>{base::_exception<T, EC, E, exception_ptr_rethrow>(std::forward<Impl>(self))};
}
if(base::_has_error(std::forward<Impl>(self)))
{
detail::_rethrow_exception<trait::is_exception_ptr_available<EC>::value>{base::_error(std::forward<Impl>(self))};
}
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no value")); // NOLINT
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self)
{
if(!base::_has_error(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no error")); // NOLINT
}
}
template <class Impl> static constexpr void wide_exception_check(Impl &&self)
{
if(!base::_has_exception(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no exception")); // NOLINT
}
}
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,73 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_RESULT_ERROR_CODE_THROW_AS_SYSTEM_ERROR_HPP
#define BOOST_OUTCOME_POLICY_RESULT_ERROR_CODE_THROW_AS_SYSTEM_ERROR_HPP
#include "../bad_access.hpp"
#include "base.hpp"
#include <system_error>
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
template <class T, class EC, class E> struct error_code_throw_as_system_error;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class EC> struct error_code_throw_as_system_error<T, EC, void> : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(std::forward<Impl>(self)))
{
if(base::_has_error(std::forward<Impl>(self)))
{
// ADL discovered
outcome_throw_as_system_error_with_payload(base::_error(std::forward<Impl>(self)));
}
BOOST_OUTCOME_THROW_EXCEPTION(bad_result_access("no value")); // NOLINT
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self)
{
if(!base::_has_error(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_result_access("no error")); // NOLINT
}
}
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,71 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_RESULT_EXCEPTION_PTR_RETHROW_HPP
#define BOOST_OUTCOME_POLICY_RESULT_EXCEPTION_PTR_RETHROW_HPP
#include "../bad_access.hpp"
#include "base.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class EC, class E> struct exception_ptr_rethrow;
template <class T, class EC> struct exception_ptr_rethrow<T, EC, void> : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(std::forward<Impl>(self)))
{
if(base::_has_error(std::forward<Impl>(self)))
{
// ADL
rethrow_exception(policy::exception_ptr(base::_error(std::forward<Impl>(self))));
}
BOOST_OUTCOME_THROW_EXCEPTION(bad_result_access("no value")); // NOLINT
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self)
{
if(!base::_has_error(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_result_access("no error")); // NOLINT
}
}
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,73 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_TERMINATE_HPP
#define BOOST_OUTCOME_POLICY_TERMINATE_HPP
#include "base.hpp"
#include <cstdlib>
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition terminate. Potential doc page: `terminate`
*/
struct terminate : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(static_cast<Impl &&>(self)))
{
std::abort();
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self) noexcept
{
if(!base::_has_error(static_cast<Impl &&>(self)))
{
std::abort();
}
}
template <class Impl> static constexpr void wide_exception_check(Impl &&self)
{
if(!base::_has_exception(static_cast<Impl &&>(self)))
{
std::abort();
}
}
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,93 @@
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: Oct 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_POLICY_THROW_BAD_RESULT_ACCESS_HPP
#define BOOST_OUTCOME_POLICY_THROW_BAD_RESULT_ACCESS_HPP
#include "../bad_access.hpp"
#include "base.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition throw_bad_result_access. Potential doc page: NOT FOUND
*/
template <class EC, class EP> struct throw_bad_result_access : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no value")); // NOLINT
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self)
{
if(!base::_has_error(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no error")); // NOLINT
}
}
template <class Impl> static constexpr void wide_exception_check(Impl &&self)
{
if(!base::_has_exception(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_outcome_access("no exception")); // NOLINT
}
}
};
template <class EC> struct throw_bad_result_access<EC, void> : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(std::forward<Impl>(self)))
{
if(base::_has_error(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_result_access_with<EC>(base::_error(std::forward<Impl>(self))));
}
BOOST_OUTCOME_THROW_EXCEPTION(bad_result_access("no value")); // NOLINT
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self)
{
if(!base::_has_error(std::forward<Impl>(self)))
{
BOOST_OUTCOME_THROW_EXCEPTION(bad_result_access("no error")); // NOLINT
}
}
};
} // namespace policy
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,53 @@
/* A very simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_RESULT_HPP
#define BOOST_OUTCOME_RESULT_HPP
#include "boost_result.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
/*! In standalone Outcome, this aliases `std_result<>`. In Boost.Outcome, this aliases `boost_result<>`.
*/
template <class R, class S = boost::system::error_code, class NoValuePolicy = policy::default_policy<R, S, void>> //
using result = boost_result<R, S, NoValuePolicy>;
/*! In standalone Outcome, this aliases `std_unchecked<>`. In Boost.Outcome, this aliases `boost_checked<>`.
*/
template <class R, class S = boost::system::error_code> using unchecked = result<R, S, policy::all_narrow>;
/*! In standalone Outcome, this aliases `std_checked<>`. In Boost.Outcome, this aliases `boost_checked<>`.
*/
template <class R, class S = boost::system::error_code> using checked = result<R, S, policy::throw_bad_result_access<S, void>>;
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,4 @@
// 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

View File

@@ -0,0 +1,55 @@
/* A less simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_STD_OUTCOME_HPP
#define BOOST_OUTCOME_STD_OUTCOME_HPP
#include "basic_outcome.hpp"
#include "std_result.hpp"
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
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S = std::error_code, class P = std::exception_ptr, class NoValuePolicy = policy::default_policy<R, S, P>> //
using std_outcome = basic_outcome<R, S, P, NoValuePolicy>;
BOOST_OUTCOME_V2_NAMESPACE_END
#include "policy/outcome_error_code_throw_as_system_error.hpp"
#include "policy/outcome_exception_ptr_rethrow.hpp"
#endif

View File

@@ -0,0 +1,83 @@
/* A very simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: June 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_STD_RESULT_HPP
#define BOOST_OUTCOME_STD_RESULT_HPP
#include "basic_result.hpp"
#include "detail/trait_std_error_code.hpp"
#include "detail/trait_std_exception.hpp"
#include "policy/fail_to_compile_observers.hpp"
#include "policy/result_error_code_throw_as_system_error.hpp"
#include "policy/result_exception_ptr_rethrow.hpp"
#include "policy/throw_bad_result_access.hpp"
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class EC, class E>
using default_policy = std::conditional_t< //
std::is_void<EC>::value && std::is_void<E>::value,
terminate, //
std::conditional_t< //
trait::is_error_code_available<EC>::value, error_code_throw_as_system_error<T, EC, E>, //
std::conditional_t< //
trait::is_exception_ptr_available<EC>::value || trait::is_exception_ptr_available<E>::value, exception_ptr_rethrow<T, EC, E>, //
fail_to_compile_observers //
>>>;
} // namespace policy
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S = std::error_code, class NoValuePolicy = policy::default_policy<R, S, void>> //
using std_result = basic_result<R, S, NoValuePolicy>;
/*! AWAITING HUGO JSON CONVERSION TOOL
type alias template <class R, class S = std::error_code> std_unchecked. Potential doc page: `std_unchecked<T, E = std::error_code>`
*/
template <class R, class S = std::error_code> using std_unchecked = std_result<R, S, policy::all_narrow>;
/*! AWAITING HUGO JSON CONVERSION TOOL
type alias template <class R, class S = std::error_code> std_checked. Potential doc page: `std_checked<T, E = std::error_code>`
*/
template <class R, class S = std::error_code> using std_checked = std_result<R, S, policy::throw_bad_result_access<S, void>>;
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,250 @@
/* Type sugar for success and failure
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: July 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_SUCCESS_FAILURE_HPP
#define BOOST_OUTCOME_SUCCESS_FAILURE_HPP
#include "config.hpp"
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class T> success_type. Potential doc page: `success_type<T>`
*/
template <class T> struct BOOST_OUTCOME_NODISCARD success_type
{
using value_type = T;
private:
value_type _value;
public:
success_type() = default;
success_type(const success_type &) = default;
success_type(success_type &&) = default; // NOLINT
success_type &operator=(const success_type &) = default;
success_type &operator=(success_type &&) = default; // NOLINT
~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)
: _value(static_cast<U &&>(v)) // NOLINT
{
}
constexpr value_type &value() & { return _value; }
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); }
};
template <> struct BOOST_OUTCOME_NODISCARD success_type<void>
{
using value_type = void;
};
/*! Returns type sugar for implicitly constructing a `basic_result<T>` with a successful state,
default constructing `T` if necessary.
*/
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.
*/
template <class T> inline constexpr success_type<std::decay_t<T>> success(T &&v)
{
return success_type<std::decay_t<T>>{static_cast<T &&>(v)};
}
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class EC, class E = void> failure_type. Potential doc page: `failure_type<EC, EP = void>`
*/
template <class EC, class E = void> struct BOOST_OUTCOME_NODISCARD failure_type
{
using error_type = EC;
using exception_type = E;
private:
bool _have_error{}, _have_exception{};
error_type _error;
exception_type _exception;
struct error_init_tag
{
};
struct exception_init_tag
{
};
public:
failure_type() = default;
failure_type(const failure_type &) = default;
failure_type(failure_type &&) = default; // NOLINT
failure_type &operator=(const failure_type &) = default;
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))
, _exception(static_cast<V &&>(v))
{
}
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))
, _exception()
{
}
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()
, _exception(static_cast<U &&>(u))
{
}
constexpr bool has_error() const { return _have_error; }
constexpr bool has_exception() const { return _have_exception; }
constexpr error_type &error() & { return _error; }
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 exception_type &exception() & { return _exception; }
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); }
};
template <class EC> struct BOOST_OUTCOME_NODISCARD failure_type<EC, void>
{
using error_type = EC;
using exception_type = void;
private:
error_type _error;
public:
failure_type() = default;
failure_type(const failure_type &) = default;
failure_type(failure_type &&) = default; // NOLINT
failure_type &operator=(const failure_type &) = default;
failure_type &operator=(failure_type &&) = default; // NOLINT
~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)
: _error(static_cast<U &&>(u)) // NOLINT
{
}
constexpr error_type &error() & { return _error; }
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); }
};
template <class E> struct BOOST_OUTCOME_NODISCARD failure_type<void, E>
{
using error_type = void;
using exception_type = E;
private:
exception_type _exception;
public:
failure_type() = default;
failure_type(const failure_type &) = default;
failure_type(failure_type &&) = default; // NOLINT
failure_type &operator=(const failure_type &) = default;
failure_type &operator=(failure_type &&) = default; // NOLINT
~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)
: _exception(static_cast<V &&>(v)) // NOLINT
{
}
constexpr exception_type &exception() & { return _exception; }
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); }
};
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class EC> inline constexpr failure_type<std::decay_t<EC>> failure(EC &&v)
{
return failure_type<std::decay_t<EC>>{static_cast<EC &&>(v)};
}
/*! 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)
{
return failure_type<std::decay_t<EC>, std::decay_t<E>>{static_cast<EC &&>(v), static_cast<E &&>(w)};
}
namespace detail
{
template <class T> struct is_success_type
{
static constexpr bool value = false;
};
template <class T> struct is_success_type<success_type<T>>
{
static constexpr bool value = true;
};
template <class T> struct is_failure_type
{
static constexpr bool value = false;
};
template <class EC, class E> struct is_failure_type<failure_type<EC, E>>
{
static constexpr bool value = true;
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> static constexpr bool is_success_type = detail::is_success_type<std::decay_t<T>>::value;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> static constexpr bool is_failure_type = detail::is_failure_type<std::decay_t<T>>::value;
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,131 @@
/* Traits for Outcome
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: March 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_TRAIT_HPP
#define BOOST_OUTCOME_TRAIT_HPP
#include "config.hpp"
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
namespace trait
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R> //
static constexpr bool type_can_be_used_in_basic_result = //
(!std::is_reference<R>::value //
&& !BOOST_OUTCOME_V2_NAMESPACE::detail::is_in_place_type_t<std::decay_t<R>>::value //
&& !is_success_type<R> //
&& !is_failure_type<R> //
&& !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
type definition is_error_type. Potential doc page: NOT FOUND
*/
template <class E> struct is_error_type
{
static constexpr bool value = false;
};
/*! 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
{
static constexpr bool value = false;
};
namespace detail
{
template <class T> using devoid = BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<T>;
template <class T> std::add_rvalue_reference_t<devoid<T>> declval() noexcept;
// From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4436.pdf
namespace detector_impl
{
template <class...> using void_t = void;
template <class Default, class, template <class...> class Op, class... Args> struct detector
{
static constexpr bool value = false;
using type = Default;
};
template <class Default, template <class...> class Op, class... Args> struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
static constexpr bool value = true;
using type = Op<Args...>;
};
} // namespace detector_impl
template <template <class...> class Op, class... Args> using is_detected = detector_impl::detector<void, void, Op, Args...>;
template <class Arg> using result_of_make_error_code = decltype(make_error_code(declval<Arg>()));
template <class Arg> using introspect_make_error_code = is_detected<result_of_make_error_code, Arg>;
template <class Arg> using result_of_make_exception_ptr = decltype(make_exception_ptr(declval<Arg>()));
template <class Arg> using introspect_make_exception_ptr = is_detected<result_of_make_exception_ptr, Arg>;
template <class T> struct _is_error_code_available
{
static constexpr bool value = detail::introspect_make_error_code<T>::value;
};
template <class T> struct _is_exception_ptr_available
{
static constexpr bool value = detail::introspect_make_exception_ptr<T>::value;
};
} // namespace detail
/*! 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;
};
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
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;
};
template <class T> constexpr bool is_exception_ptr_available_v = detail::_is_exception_ptr_available<std::decay<T>>::value;
} // namespace trait
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,150 @@
/* Try operation macros
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: July 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_TRY_HPP
#define BOOST_OUTCOME_TRY_HPP
#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
{
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(); }
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
#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__)
#define BOOST_OUTCOME_TRY_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
#define BOOST_OUTCOME_TRY_EXPAND_ARGS(args) BOOST_OUTCOME_TRY_RETURN_ARG_COUNT args
#define BOOST_OUTCOME_TRY_COUNT_ARGS_MAX8(...) BOOST_OUTCOME_TRY_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define BOOST_OUTCOME_TRY_OVERLOAD_MACRO2(name, count) name##count
#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__))
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wparentheses"
#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))
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define BOOST_OUTCOME_TRYV(...) BOOST_OUTCOME_TRYV2(BOOST_OUTCOME_TRY_UNIQUE_NAME, __VA_ARGS__)
#if defined(__GNUC__) || defined(__clang__)
/*! 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)); \
\
})
#endif
/*! 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_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)
#define BOOST_OUTCOME_TRY_INVOKE_TRY6(a, b, c, d, e, f) BOOST_OUTCOME_TRYA(a, b, c, d, e, f)
#define BOOST_OUTCOME_TRY_INVOKE_TRY5(a, b, c, d, e) BOOST_OUTCOME_TRYA(a, b, c, d, e)
#define BOOST_OUTCOME_TRY_INVOKE_TRY4(a, b, c, d) BOOST_OUTCOME_TRYA(a, b, c, d)
#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
SIGNATURE NOT RECOGNISED
*/
#define BOOST_OUTCOME_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_TRY_INVOKE_TRY, __VA_ARGS__)
#endif

View File

@@ -0,0 +1,144 @@
/* Tries to convert an exception ptr into its equivalent error code
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
File Created: July 2017
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef BOOST_OUTCOME_UTILS_HPP
#define BOOST_OUTCOME_UTILS_HPP
#include "config.hpp"
#include <exception>
#include <system_error>
BOOST_OUTCOME_V2_NAMESPACE_BEGIN
#ifndef BOOST_NO_EXCEPTIONS
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
inline std::error_code error_from_exception(std::exception_ptr &&ep = std::current_exception(), std::error_code not_matched = std::make_error_code(std::errc::resource_unavailable_try_again)) noexcept
{
if(!ep)
{
return {};
}
try
{
std::rethrow_exception(ep);
}
catch(const std::invalid_argument & /*unused*/)
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::invalid_argument);
}
catch(const std::domain_error & /*unused*/)
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::argument_out_of_domain);
}
catch(const std::length_error & /*unused*/)
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::argument_list_too_long);
}
catch(const std::out_of_range & /*unused*/)
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::result_out_of_range);
}
catch(const std::logic_error & /*unused*/) /* base class for this group */
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::invalid_argument);
}
catch(const std::system_error &e) /* also catches ios::failure */
{
ep = std::exception_ptr();
return e.code();
}
catch(const std::overflow_error & /*unused*/)
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::value_too_large);
}
catch(const std::range_error & /*unused*/)
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::result_out_of_range);
}
catch(const std::runtime_error & /*unused*/) /* base class for this group */
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::resource_unavailable_try_again);
}
catch(const std::bad_alloc & /*unused*/)
{
ep = std::exception_ptr();
return std::make_error_code(std::errc::not_enough_memory);
}
catch(...)
{
}
return not_matched;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
inline void try_throw_std_exception_from_error(std::error_code ec, const std::string &msg = std::string{})
{
if(!ec || (ec.category() != std::generic_category()
#ifndef _WIN32
&& ec.category() != std::system_category()
#endif
))
{
return;
}
switch(ec.value())
{
case EINVAL:
throw msg.empty() ? std::invalid_argument("invalid argument") : std::invalid_argument(msg);
case EDOM:
throw msg.empty() ? std::domain_error("domain error") : std::domain_error(msg);
case E2BIG:
throw msg.empty() ? std::length_error("length error") : std::length_error(msg);
case ERANGE:
throw msg.empty() ? std::out_of_range("out of range") : std::out_of_range(msg);
case EOVERFLOW:
throw msg.empty() ? std::overflow_error("overflow error") : std::overflow_error(msg);
case ENOMEM:
throw std::bad_alloc();
}
}
#endif
BOOST_OUTCOME_V2_NAMESPACE_END
#endif

View File

@@ -0,0 +1,13 @@
/*! 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