mirror of
https://github.com/boostorg/leaf.git
synced 2026-01-31 08:12:26 +00:00
Merged exception/noexception error handling into one file
This commit is contained in:
@@ -2905,16 +2905,6 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
decltype(std::declval<TryBlock>()()) try_catch_( TryBlock &&, H && ... );
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
try_handle_all( TryBlock &&, H && ... h );
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
try_handle_some( TryBlock &&, H && ... );
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
@@ -3020,24 +3010,6 @@ namespace boost { namespace leaf {
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
// >>> #include <boost/leaf/detail/handle.hpp>
|
||||
#line 1 "boost/leaf/detail/handle.hpp"
|
||||
#ifndef BOOST_LEAF_DETAIL_HANDLE_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_HANDLE_HPP_INCLUDED
|
||||
|
||||
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang system_header
|
||||
#elif (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
// >>> #include <boost/leaf/detail/demangle.hpp>
|
||||
#line 1 "boost/leaf/detail/demangle.hpp"
|
||||
#ifndef BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED
|
||||
@@ -3170,7 +3142,9 @@ namespace boost { namespace leaf {
|
||||
|
||||
#endif
|
||||
// <<< #include <boost/leaf/detail/demangle.hpp>
|
||||
#line 19 "boost/leaf/detail/handle.hpp"
|
||||
#line 19 "boost/leaf/handle_errors.hpp"
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
@@ -3572,6 +3546,15 @@ namespace boost { namespace leaf {
|
||||
return peek<typename std::decay<A>::type>(tup, ei);
|
||||
}
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
std::exception const *
|
||||
handler_argument_traits<void>::
|
||||
check( Tup const &, error_info const & ei ) noexcept
|
||||
{
|
||||
return ei.exception();
|
||||
}
|
||||
|
||||
template <class Tup, class... List>
|
||||
struct check_arguments;
|
||||
|
||||
@@ -3746,156 +3729,63 @@ namespace boost { namespace leaf {
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#ifdef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
// Creating a named temp on purpose, to avoid C++11 and C++14 zero-initializing the context.
|
||||
context_type_from_handlers<H...> c;
|
||||
return c.try_handle_all( std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
|
||||
return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
// Creating a named temp on purpose, to avoid C++11 and C++14 zero-initializing the context.
|
||||
context_type_from_handlers<H...> c;
|
||||
return c.try_handle_some( std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
// <<< #include <boost/leaf/detail/handle.hpp>
|
||||
#line 18 "boost/leaf/handle_errors.hpp"
|
||||
|
||||
#ifdef BOOST_LEAF_NO_EXCEPTIONS
|
||||
// >>> # include <boost/leaf/detail/ctx_nocatch.hpp>
|
||||
#line 1 "boost/leaf/detail/ctx_nocatch.hpp"
|
||||
#ifndef BOOST_LEAF_DETAIL_CTX_NOCATCH_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_CTX_NOCATCH_HPP_INCLUDED
|
||||
|
||||
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang system_header
|
||||
#elif (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# error This header requires exception handling to be disabled
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
context<E...>::
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
this->deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
|
||||
return this->template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
context<E...>::
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
this->deactivate();
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
|
||||
auto rr = this->template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
ctx.propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
// <<< # include <boost/leaf/detail/ctx_nocatch.hpp>
|
||||
#line 21 "boost/leaf/handle_errors.hpp"
|
||||
#else
|
||||
// >>> # include <boost/leaf/detail/ctx_catch.hpp>
|
||||
#line 1 "boost/leaf/detail/ctx_catch.hpp"
|
||||
#ifndef BOOST_LEAF_DETAIL_CTX_CATCH_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_CTX_CATCH_HPP_INCLUDED
|
||||
|
||||
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang system_header
|
||||
#elif (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# error This header requires exception handling
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
std::exception const *
|
||||
handler_argument_traits<void>::
|
||||
check( Tup const &, error_info const & ei ) noexcept
|
||||
{
|
||||
return ei.exception();
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
context<E...>::
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
@@ -3905,24 +3795,23 @@ namespace boost { namespace leaf {
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
if( this->is_active() )
|
||||
this->deactivate();
|
||||
if( ctx.is_active() )
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
|
||||
return this->template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
context<E...>::
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
@@ -3932,12 +3821,12 @@ namespace boost { namespace leaf {
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
if( this->is_active() )
|
||||
this->deactivate();
|
||||
if( ctx.is_active() )
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
|
||||
auto rr = this->template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
ctx.propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
@@ -3989,8 +3878,6 @@ namespace boost { namespace leaf {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
decltype(std::declval<TryBlock>()())
|
||||
@@ -4007,8 +3894,12 @@ namespace boost { namespace leaf {
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} }
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
// Boost Exception Integration
|
||||
|
||||
namespace boost { class exception; }
|
||||
@@ -4071,9 +3962,6 @@ namespace boost { namespace leaf {
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
// <<< # include <boost/leaf/detail/ctx_catch.hpp>
|
||||
#line 23 "boost/leaf/handle_errors.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -251,16 +251,6 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
decltype(std::declval<TryBlock>()()) try_catch_( TryBlock &&, H && ... );
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
try_handle_all( TryBlock &&, H && ... h );
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
try_handle_some( TryBlock &&, H && ... );
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
#ifndef BOOST_LEAF_DETAIL_CTX_CATCH_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_CTX_CATCH_HPP_INCLUDED
|
||||
|
||||
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang system_header
|
||||
#elif (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# error This header requires exception handling
|
||||
#endif
|
||||
|
||||
#include <boost/leaf/capture.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
std::exception const *
|
||||
handler_argument_traits<void>::
|
||||
check( Tup const &, error_info const & ei ) noexcept
|
||||
{
|
||||
return ei.exception();
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
context<E...>::
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...) )
|
||||
return r.value();
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
if( this->is_active() )
|
||||
this->deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
|
||||
return this->template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
context<E...>::
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...) )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
if( this->is_active() )
|
||||
this->deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
|
||||
auto rr = this->template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
inline
|
||||
decltype(std::declval<TryBlock>()())
|
||||
context<E...>::
|
||||
try_catch_( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
BOOST_LEAF_ASSERT(is_active());
|
||||
using R = decltype(std::declval<TryBlock>()());
|
||||
try
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
}
|
||||
catch( capturing_exception const & cap )
|
||||
{
|
||||
try
|
||||
{
|
||||
cap.unload_and_rethrow_original_exception();
|
||||
}
|
||||
catch( std::exception & ex )
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(&ex), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(nullptr), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
}
|
||||
catch( std::exception & ex )
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(&ex), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(nullptr), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
decltype(std::declval<TryBlock>()())
|
||||
try_catch( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
auto active_context = activate_context(ctx);
|
||||
return ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
// Boost Exception Integration
|
||||
|
||||
namespace boost { class exception; }
|
||||
namespace boost { template <class Tag,class T> class error_info; }
|
||||
namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class T>
|
||||
struct match_enum_type;
|
||||
|
||||
template <class Tag, class T>
|
||||
struct match_enum_type<boost::error_info<Tag, T>>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class Ex>
|
||||
BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
|
||||
{
|
||||
return dynamic_cast<Ex *>(ei.exception());
|
||||
}
|
||||
|
||||
template <class, class T>
|
||||
struct dependent_type { using type = T; };
|
||||
|
||||
template <class Dep, class T>
|
||||
using dependent_type_t = typename dependent_type<Dep, T>::type;
|
||||
|
||||
template <class Tag, class T>
|
||||
struct handler_argument_traits<boost::error_info<Tag, T>>
|
||||
{
|
||||
using error_type = void;
|
||||
constexpr static bool always_available = false;
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static T * check( Tup & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
using boost_exception = dependent_type_t<T, boost::exception>;
|
||||
if( auto * be = get_exception<boost_exception>(ei) )
|
||||
return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return boost::error_info<Tag, T>(*check(tup, ei));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> const &>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> const *>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> &>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> *>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
@@ -1,70 +0,0 @@
|
||||
#ifndef BOOST_LEAF_DETAIL_CTX_NOCATCH_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_CTX_NOCATCH_HPP_INCLUDED
|
||||
|
||||
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang system_header
|
||||
#elif (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# error This header requires exception handling to be disabled
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
context<E...>::
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
this->deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
|
||||
return this->template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
context<E...>::
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
this->deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
|
||||
auto rr = this->template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
@@ -1,616 +0,0 @@
|
||||
#ifndef BOOST_LEAF_DETAIL_HANDLE_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_HANDLE_HPP_INCLUDED
|
||||
|
||||
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang system_header
|
||||
#elif (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS)
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/detail/demangle.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
class error_info
|
||||
{
|
||||
error_info & operator=( error_info const & ) = delete;
|
||||
|
||||
std::exception * const ex_;
|
||||
error_id const err_id_;
|
||||
|
||||
static error_id unpack_error_id( std::exception const * ex ) noexcept
|
||||
{
|
||||
if( std::system_error const * se = dynamic_cast<std::system_error const *>(ex) )
|
||||
return error_id(se->code());
|
||||
else if( std::error_code const * ec = dynamic_cast<std::error_code const *>(ex) )
|
||||
return error_id(*ec);
|
||||
else if( error_id const * err_id = dynamic_cast<error_id const *>(ex) )
|
||||
return *err_id;
|
||||
else
|
||||
return current_error();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
error_info( error_info const & ) noexcept = default;
|
||||
|
||||
void print( std::ostream & os ) const
|
||||
{
|
||||
os << "Error ID = " << err_id_.value();
|
||||
if( ex_ )
|
||||
{
|
||||
os <<
|
||||
"\nException dynamic type: " << leaf_detail::demangle(typeid(*ex_).name()) <<
|
||||
"\nstd::exception::what(): " << ex_->what();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
BOOST_LEAF_CONSTEXPR explicit error_info( error_id id ) noexcept:
|
||||
ex_(0),
|
||||
err_id_(id)
|
||||
{
|
||||
}
|
||||
|
||||
explicit error_info( std::exception * ex ) noexcept:
|
||||
ex_(ex),
|
||||
err_id_(unpack_error_id(ex_))
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR error_id error() const noexcept
|
||||
{
|
||||
return err_id_;
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
|
||||
{
|
||||
return ex_;
|
||||
}
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, error_info const & x )
|
||||
{
|
||||
os << "leaf::error_info: ";
|
||||
x.print(os);
|
||||
return os << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#if BOOST_LEAF_DIAGNOSTICS
|
||||
|
||||
class diagnostic_info: public error_info
|
||||
{
|
||||
leaf_detail::e_unexpected_count const * e_uc_;
|
||||
void const * tup_;
|
||||
void (*print_)( std::ostream &, void const * tup, int key_to_print );
|
||||
|
||||
protected:
|
||||
|
||||
diagnostic_info( diagnostic_info const & ) noexcept = default;
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
|
||||
error_info(ei),
|
||||
e_uc_(e_uc),
|
||||
tup_(&tup),
|
||||
print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, diagnostic_info const & x )
|
||||
{
|
||||
os << "leaf::diagnostic_info for ";
|
||||
x.print(os);
|
||||
os << ":\n";
|
||||
x.print_(os, x.tup_, x.error().value());
|
||||
if( x.e_uc_ )
|
||||
x.e_uc_->print(os);
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct diagnostic_info_: diagnostic_info
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
|
||||
diagnostic_info(ei, e_uc, tup)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<e_unexpected_count>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_count>::check(tup, ei), tup);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class diagnostic_info: public error_info
|
||||
{
|
||||
protected:
|
||||
|
||||
diagnostic_info( diagnostic_info const & ) noexcept = default;
|
||||
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei ) noexcept:
|
||||
error_info(ei)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, diagnostic_info const & x )
|
||||
{
|
||||
os <<
|
||||
"leaf::diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
|
||||
"leaf::error_info: ";
|
||||
x.print(os);
|
||||
return os << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct diagnostic_info_: diagnostic_info
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei ) noexcept:
|
||||
diagnostic_info(ei)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return diagnostic_info_(ei);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#if BOOST_LEAF_DIAGNOSTICS
|
||||
|
||||
class verbose_diagnostic_info: public error_info
|
||||
{
|
||||
leaf_detail::e_unexpected_info const * e_ui_;
|
||||
void const * tup_;
|
||||
void (*print_)( std::ostream &, void const * tup, int key_to_print );
|
||||
|
||||
protected:
|
||||
|
||||
verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
|
||||
error_info(ei),
|
||||
e_ui_(e_ui),
|
||||
tup_(&tup),
|
||||
print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, verbose_diagnostic_info const & x )
|
||||
{
|
||||
os << "leaf::verbose_diagnostic_info for ";
|
||||
x.print(os);
|
||||
os << ":\n";
|
||||
x.print_(os, x.tup_, x.error().value());
|
||||
if( x.e_ui_ )
|
||||
x.e_ui_->print(os);
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct verbose_diagnostic_info_: verbose_diagnostic_info
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
|
||||
verbose_diagnostic_info(ei, e_ui, tup)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<e_unexpected_info>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return verbose_diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_info>::check(tup, ei), tup);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class verbose_diagnostic_info: public error_info
|
||||
{
|
||||
protected:
|
||||
|
||||
verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
|
||||
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei ) noexcept:
|
||||
error_info(ei)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, verbose_diagnostic_info const & x )
|
||||
{
|
||||
os <<
|
||||
"leaf::verbose_diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
|
||||
"leaf::error_info: ";
|
||||
x.print(os);
|
||||
return os << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct verbose_diagnostic_info_: verbose_diagnostic_info
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei ) noexcept:
|
||||
verbose_diagnostic_info(ei)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return verbose_diagnostic_info_(ei);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class T, class... List>
|
||||
struct type_index;
|
||||
|
||||
template <class T, class... Cdr>
|
||||
struct type_index<T, T, Cdr...>
|
||||
{
|
||||
constexpr static int value = 0;
|
||||
};
|
||||
|
||||
template <class T, class Car, class... Cdr>
|
||||
struct type_index<T, Car, Cdr...>
|
||||
{
|
||||
constexpr static int value = 1 + type_index<T,Cdr...>::value;
|
||||
};
|
||||
|
||||
template <class T, class Tuple>
|
||||
struct tuple_type_index;
|
||||
|
||||
template <class T, class... TupleTypes>
|
||||
struct tuple_type_index<T,std::tuple<TupleTypes...>>
|
||||
{
|
||||
constexpr static int value = type_index<T,TupleTypes...>::value;
|
||||
};
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
template <class E, bool = std::is_class<E>::value>
|
||||
struct peek_exception;
|
||||
|
||||
template <>
|
||||
struct peek_exception<std::exception, true>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
|
||||
{
|
||||
return ei.exception();
|
||||
}
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct peek_exception<E, true>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ei ) noexcept
|
||||
{
|
||||
return dynamic_cast<E *>(ei.exception());
|
||||
}
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct peek_exception<E, false>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class E, class SlotsTuple>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
E const *
|
||||
peek( SlotsTuple const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
if( error_id err = ei.error() )
|
||||
if( E const * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
|
||||
return e;
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
else
|
||||
return peek_exception<E const>::peek(ei);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class E, class SlotsTuple>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
E *
|
||||
peek( SlotsTuple & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
if( error_id err = ei.error() )
|
||||
if( E * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
|
||||
return e;
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
else
|
||||
return peek_exception<E>::peek(ei);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class A>
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename handler_argument_traits_defaults<A, false>::error_type const *
|
||||
handler_argument_traits_defaults<A, false>::
|
||||
check( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return peek<typename std::decay<A>::type>(tup, ei);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename handler_argument_traits_defaults<A, false>::error_type *
|
||||
handler_argument_traits_defaults<A, false>::
|
||||
check( Tup & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return peek<typename std::decay<A>::type>(tup, ei);
|
||||
}
|
||||
|
||||
template <class Tup, class... List>
|
||||
struct check_arguments;
|
||||
|
||||
template <class Tup>
|
||||
struct check_arguments<Tup>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tup, class Car, class... Cdr>
|
||||
struct check_arguments<Tup, Car, Cdr...>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class>
|
||||
struct handler_matches_any_error: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <template<class...> class L>
|
||||
struct handler_matches_any_error<L<>>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <template<class...> class L, class Car, class... Cdr>
|
||||
struct handler_matches_any_error<L<Car, Cdr...>>
|
||||
{
|
||||
constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class Tup, class... A>
|
||||
BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
|
||||
{
|
||||
return check_arguments<Tup, A...>::check(tup, ei);
|
||||
}
|
||||
|
||||
template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
|
||||
struct handler_caller
|
||||
{
|
||||
template <class Tup, class... A>
|
||||
BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
|
||||
{
|
||||
return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
|
||||
}
|
||||
};
|
||||
|
||||
template <template <class...> class Result, class... E, class F>
|
||||
struct handler_caller<Result<void, E...>, F, true, void>
|
||||
{
|
||||
using R = Result<void, E...>;
|
||||
|
||||
template <class Tup, class... A>
|
||||
BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
|
||||
{
|
||||
std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
|
||||
return { };
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_tuple: std::false_type { };
|
||||
|
||||
template <class... T>
|
||||
struct is_tuple<std::tuple<T...>>: std::true_type { };
|
||||
|
||||
template <class... T>
|
||||
struct is_tuple<std::tuple<T...> &>: std::true_type { };
|
||||
|
||||
template <class R, class Tup, class H>
|
||||
BOOST_LEAF_CONSTEXPR
|
||||
inline
|
||||
typename std::enable_if<!is_tuple<H>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, H && h )
|
||||
{
|
||||
static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
|
||||
return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
|
||||
}
|
||||
|
||||
template <class R, class Tup, class Car, class... Cdr>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::enable_if<!is_tuple<Car>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
|
||||
{
|
||||
if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
|
||||
return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
|
||||
else
|
||||
return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
|
||||
}
|
||||
|
||||
template <class R, class Tup, class HTup, size_t ... I>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
R
|
||||
handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
|
||||
{
|
||||
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
|
||||
}
|
||||
|
||||
template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
R
|
||||
handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
|
||||
{
|
||||
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
|
||||
}
|
||||
|
||||
template <class R, class Tup, class H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::enable_if<is_tuple<H>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, H && h )
|
||||
{
|
||||
return handle_error_tuple_<R>(
|
||||
tup,
|
||||
ei,
|
||||
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
|
||||
std::forward<H>(h));
|
||||
}
|
||||
|
||||
template <class R, class Tup, class Car, class... Cdr>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::enable_if<is_tuple<Car>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
|
||||
{
|
||||
return handle_error_tuple_<R>(
|
||||
tup,
|
||||
ei,
|
||||
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
|
||||
std::forward<Car>(car),
|
||||
std::forward<Cdr>(cdr)...);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
R
|
||||
context<E...>::
|
||||
handle_error( error_id id, H && ... h ) const
|
||||
{
|
||||
BOOST_LEAF_ASSERT(!is_active());
|
||||
return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
R
|
||||
context<E...>::
|
||||
handle_error( error_id id, H && ... h )
|
||||
{
|
||||
BOOST_LEAF_ASSERT(!is_active());
|
||||
return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
// Creating a named temp on purpose, to avoid C++11 and C++14 zero-initializing the context.
|
||||
context_type_from_handlers<H...> c;
|
||||
return c.try_handle_all( std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
}
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
// Creating a named temp on purpose, to avoid C++11 and C++14 zero-initializing the context.
|
||||
context_type_from_handlers<H...> c;
|
||||
return c.try_handle_some( std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
@@ -14,12 +14,828 @@
|
||||
# pragma warning(push,1)
|
||||
#endif
|
||||
|
||||
#include <boost/leaf/detail/handle.hpp>
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/detail/demangle.hpp>
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# include <boost/leaf/capture.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
class error_info
|
||||
{
|
||||
error_info & operator=( error_info const & ) = delete;
|
||||
|
||||
std::exception * const ex_;
|
||||
error_id const err_id_;
|
||||
|
||||
static error_id unpack_error_id( std::exception const * ex ) noexcept
|
||||
{
|
||||
if( std::system_error const * se = dynamic_cast<std::system_error const *>(ex) )
|
||||
return error_id(se->code());
|
||||
else if( std::error_code const * ec = dynamic_cast<std::error_code const *>(ex) )
|
||||
return error_id(*ec);
|
||||
else if( error_id const * err_id = dynamic_cast<error_id const *>(ex) )
|
||||
return *err_id;
|
||||
else
|
||||
return current_error();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
error_info( error_info const & ) noexcept = default;
|
||||
|
||||
void print( std::ostream & os ) const
|
||||
{
|
||||
os << "Error ID = " << err_id_.value();
|
||||
if( ex_ )
|
||||
{
|
||||
os <<
|
||||
"\nException dynamic type: " << leaf_detail::demangle(typeid(*ex_).name()) <<
|
||||
"\nstd::exception::what(): " << ex_->what();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
BOOST_LEAF_CONSTEXPR explicit error_info( error_id id ) noexcept:
|
||||
ex_(0),
|
||||
err_id_(id)
|
||||
{
|
||||
}
|
||||
|
||||
explicit error_info( std::exception * ex ) noexcept:
|
||||
ex_(ex),
|
||||
err_id_(unpack_error_id(ex_))
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR error_id error() const noexcept
|
||||
{
|
||||
return err_id_;
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
|
||||
{
|
||||
return ex_;
|
||||
}
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, error_info const & x )
|
||||
{
|
||||
os << "leaf::error_info: ";
|
||||
x.print(os);
|
||||
return os << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#if BOOST_LEAF_DIAGNOSTICS
|
||||
|
||||
class diagnostic_info: public error_info
|
||||
{
|
||||
leaf_detail::e_unexpected_count const * e_uc_;
|
||||
void const * tup_;
|
||||
void (*print_)( std::ostream &, void const * tup, int key_to_print );
|
||||
|
||||
protected:
|
||||
|
||||
diagnostic_info( diagnostic_info const & ) noexcept = default;
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
|
||||
error_info(ei),
|
||||
e_uc_(e_uc),
|
||||
tup_(&tup),
|
||||
print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, diagnostic_info const & x )
|
||||
{
|
||||
os << "leaf::diagnostic_info for ";
|
||||
x.print(os);
|
||||
os << ":\n";
|
||||
x.print_(os, x.tup_, x.error().value());
|
||||
if( x.e_uc_ )
|
||||
x.e_uc_->print(os);
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct diagnostic_info_: diagnostic_info
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
|
||||
diagnostic_info(ei, e_uc, tup)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<e_unexpected_count>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_count>::check(tup, ei), tup);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class diagnostic_info: public error_info
|
||||
{
|
||||
protected:
|
||||
|
||||
diagnostic_info( diagnostic_info const & ) noexcept = default;
|
||||
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei ) noexcept:
|
||||
error_info(ei)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, diagnostic_info const & x )
|
||||
{
|
||||
os <<
|
||||
"leaf::diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
|
||||
"leaf::error_info: ";
|
||||
x.print(os);
|
||||
return os << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct diagnostic_info_: diagnostic_info
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei ) noexcept:
|
||||
diagnostic_info(ei)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return diagnostic_info_(ei);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#if BOOST_LEAF_DIAGNOSTICS
|
||||
|
||||
class verbose_diagnostic_info: public error_info
|
||||
{
|
||||
leaf_detail::e_unexpected_info const * e_ui_;
|
||||
void const * tup_;
|
||||
void (*print_)( std::ostream &, void const * tup, int key_to_print );
|
||||
|
||||
protected:
|
||||
|
||||
verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
|
||||
error_info(ei),
|
||||
e_ui_(e_ui),
|
||||
tup_(&tup),
|
||||
print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, verbose_diagnostic_info const & x )
|
||||
{
|
||||
os << "leaf::verbose_diagnostic_info for ";
|
||||
x.print(os);
|
||||
os << ":\n";
|
||||
x.print_(os, x.tup_, x.error().value());
|
||||
if( x.e_ui_ )
|
||||
x.e_ui_->print(os);
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct verbose_diagnostic_info_: verbose_diagnostic_info
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
|
||||
verbose_diagnostic_info(ei, e_ui, tup)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<e_unexpected_info>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return verbose_diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_info>::check(tup, ei), tup);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class verbose_diagnostic_info: public error_info
|
||||
{
|
||||
protected:
|
||||
|
||||
verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
|
||||
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei ) noexcept:
|
||||
error_info(ei)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend std::ostream & operator<<( std::ostream & os, verbose_diagnostic_info const & x )
|
||||
{
|
||||
os <<
|
||||
"leaf::verbose_diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
|
||||
"leaf::error_info: ";
|
||||
x.print(os);
|
||||
return os << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct verbose_diagnostic_info_: verbose_diagnostic_info
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei ) noexcept:
|
||||
verbose_diagnostic_info(ei)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
|
||||
{
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return verbose_diagnostic_info_(ei);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class T, class... List>
|
||||
struct type_index;
|
||||
|
||||
template <class T, class... Cdr>
|
||||
struct type_index<T, T, Cdr...>
|
||||
{
|
||||
constexpr static int value = 0;
|
||||
};
|
||||
|
||||
template <class T, class Car, class... Cdr>
|
||||
struct type_index<T, Car, Cdr...>
|
||||
{
|
||||
constexpr static int value = 1 + type_index<T,Cdr...>::value;
|
||||
};
|
||||
|
||||
template <class T, class Tuple>
|
||||
struct tuple_type_index;
|
||||
|
||||
template <class T, class... TupleTypes>
|
||||
struct tuple_type_index<T,std::tuple<TupleTypes...>>
|
||||
{
|
||||
constexpr static int value = type_index<T,TupleTypes...>::value;
|
||||
};
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
template <class E, bool = std::is_class<E>::value>
|
||||
struct peek_exception;
|
||||
|
||||
template <>
|
||||
struct peek_exception<std::exception, true>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
|
||||
{
|
||||
return ei.exception();
|
||||
}
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct peek_exception<E, true>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ei ) noexcept
|
||||
{
|
||||
return dynamic_cast<E *>(ei.exception());
|
||||
}
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct peek_exception<E, false>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class E, class SlotsTuple>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
E const *
|
||||
peek( SlotsTuple const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
if( error_id err = ei.error() )
|
||||
if( E const * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
|
||||
return e;
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
else
|
||||
return peek_exception<E const>::peek(ei);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class E, class SlotsTuple>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
E *
|
||||
peek( SlotsTuple & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
if( error_id err = ei.error() )
|
||||
if( E * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
|
||||
return e;
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
else
|
||||
return peek_exception<E>::peek(ei);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class A>
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename handler_argument_traits_defaults<A, false>::error_type const *
|
||||
handler_argument_traits_defaults<A, false>::
|
||||
check( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return peek<typename std::decay<A>::type>(tup, ei);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename handler_argument_traits_defaults<A, false>::error_type *
|
||||
handler_argument_traits_defaults<A, false>::
|
||||
check( Tup & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return peek<typename std::decay<A>::type>(tup, ei);
|
||||
}
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
std::exception const *
|
||||
handler_argument_traits<void>::
|
||||
check( Tup const &, error_info const & ei ) noexcept
|
||||
{
|
||||
return ei.exception();
|
||||
}
|
||||
|
||||
template <class Tup, class... List>
|
||||
struct check_arguments;
|
||||
|
||||
template <class Tup>
|
||||
struct check_arguments<Tup>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tup, class Car, class... Cdr>
|
||||
struct check_arguments<Tup, Car, Cdr...>
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class>
|
||||
struct handler_matches_any_error: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <template<class...> class L>
|
||||
struct handler_matches_any_error<L<>>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <template<class...> class L, class Car, class... Cdr>
|
||||
struct handler_matches_any_error<L<Car, Cdr...>>
|
||||
{
|
||||
constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class Tup, class... A>
|
||||
BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
|
||||
{
|
||||
return check_arguments<Tup, A...>::check(tup, ei);
|
||||
}
|
||||
|
||||
template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
|
||||
struct handler_caller
|
||||
{
|
||||
template <class Tup, class... A>
|
||||
BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
|
||||
{
|
||||
return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
|
||||
}
|
||||
};
|
||||
|
||||
template <template <class...> class Result, class... E, class F>
|
||||
struct handler_caller<Result<void, E...>, F, true, void>
|
||||
{
|
||||
using R = Result<void, E...>;
|
||||
|
||||
template <class Tup, class... A>
|
||||
BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
|
||||
{
|
||||
std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
|
||||
return { };
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_tuple: std::false_type { };
|
||||
|
||||
template <class... T>
|
||||
struct is_tuple<std::tuple<T...>>: std::true_type { };
|
||||
|
||||
template <class... T>
|
||||
struct is_tuple<std::tuple<T...> &>: std::true_type { };
|
||||
|
||||
template <class R, class Tup, class H>
|
||||
BOOST_LEAF_CONSTEXPR
|
||||
inline
|
||||
typename std::enable_if<!is_tuple<H>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, H && h )
|
||||
{
|
||||
static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
|
||||
return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
|
||||
}
|
||||
|
||||
template <class R, class Tup, class Car, class... Cdr>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::enable_if<!is_tuple<Car>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
|
||||
{
|
||||
if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
|
||||
return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
|
||||
else
|
||||
return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
|
||||
}
|
||||
|
||||
template <class R, class Tup, class HTup, size_t ... I>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
R
|
||||
handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
|
||||
{
|
||||
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
|
||||
}
|
||||
|
||||
template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
R
|
||||
handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
|
||||
{
|
||||
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
|
||||
}
|
||||
|
||||
template <class R, class Tup, class H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::enable_if<is_tuple<H>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, H && h )
|
||||
{
|
||||
return handle_error_tuple_<R>(
|
||||
tup,
|
||||
ei,
|
||||
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
|
||||
std::forward<H>(h));
|
||||
}
|
||||
|
||||
template <class R, class Tup, class Car, class... Cdr>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::enable_if<is_tuple<Car>::value, R>::type
|
||||
handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
|
||||
{
|
||||
return handle_error_tuple_<R>(
|
||||
tup,
|
||||
ei,
|
||||
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
|
||||
std::forward<Car>(car),
|
||||
std::forward<Cdr>(cdr)...);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
R
|
||||
context<E...>::
|
||||
handle_error( error_id id, H && ... h ) const
|
||||
{
|
||||
BOOST_LEAF_ASSERT(!is_active());
|
||||
return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
|
||||
R
|
||||
context<E...>::
|
||||
handle_error( error_id id, H && ... h )
|
||||
{
|
||||
BOOST_LEAF_ASSERT(!is_active());
|
||||
return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#ifdef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# include <boost/leaf/detail/ctx_nocatch.hpp>
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
|
||||
return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
|
||||
auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
if( !rr )
|
||||
ctx.propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
# include <boost/leaf/detail/ctx_catch.hpp>
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
|
||||
try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...) )
|
||||
return r.value();
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
if( ctx.is_active() )
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
|
||||
return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
|
||||
typename std::decay<decltype(std::declval<TryBlock>()())>::type
|
||||
try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(ctx);
|
||||
if( auto r = ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...) )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
error_id id = r.error();
|
||||
if( ctx.is_active() )
|
||||
ctx.deactivate();
|
||||
using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
|
||||
auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
|
||||
if( !rr )
|
||||
ctx.propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
inline
|
||||
decltype(std::declval<TryBlock>()())
|
||||
context<E...>::
|
||||
try_catch_( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
BOOST_LEAF_ASSERT(is_active());
|
||||
using R = decltype(std::declval<TryBlock>()());
|
||||
try
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
}
|
||||
catch( capturing_exception const & cap )
|
||||
{
|
||||
try
|
||||
{
|
||||
cap.unload_and_rethrow_original_exception();
|
||||
}
|
||||
catch( std::exception & ex )
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(&ex), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(nullptr), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
}
|
||||
catch( std::exception & ex )
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(&ex), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return handle_error_<R>(this->tup(), error_info(nullptr), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
}
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
BOOST_LEAF_CONSTEXPR inline
|
||||
decltype(std::declval<TryBlock>()())
|
||||
try_catch( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
auto active_context = activate_context(ctx);
|
||||
return ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} }
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
// Boost Exception Integration
|
||||
|
||||
namespace boost { class exception; }
|
||||
namespace boost { template <class Tag,class T> class error_info; }
|
||||
namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class T>
|
||||
struct match_enum_type;
|
||||
|
||||
template <class Tag, class T>
|
||||
struct match_enum_type<boost::error_info<Tag, T>>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class Ex>
|
||||
BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
|
||||
{
|
||||
return dynamic_cast<Ex *>(ei.exception());
|
||||
}
|
||||
|
||||
template <class, class T>
|
||||
struct dependent_type { using type = T; };
|
||||
|
||||
template <class Dep, class T>
|
||||
using dependent_type_t = typename dependent_type<Dep, T>::type;
|
||||
|
||||
template <class Tag, class T>
|
||||
struct handler_argument_traits<boost::error_info<Tag, T>>
|
||||
{
|
||||
using error_type = void;
|
||||
constexpr static bool always_available = false;
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static T * check( Tup & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
using boost_exception = dependent_type_t<T, boost::exception>;
|
||||
if( auto * be = get_exception<boost_exception>(ei) )
|
||||
return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return boost::error_info<Tag, T>(*check(tup, ei));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> const &>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> const *>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> &>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> *>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user