liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED
#define BOOST_LEAF_EXCEPTION_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)
 
#ifndef BOOST_LEAF_ENABLE_WARNINGS
#   if defined(__clang__)
#       pragma clang system_header
#   elif (__GNUC__*100+__GNUC_MINOR__>301)
#       pragma GCC system_header
#   elif defined(_MSC_VER)
#       pragma warning(push,1)
#   endif
#endif
 
#include <boost/leaf/error.hpp>
#include <exception>
 
#define BOOST_LEAF_EXCEPTION ::boost::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception
#define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::leaf_detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception
 
////////////////////////////////////////
 
namespace boost { namespace leaf {
 
    namespace leaf_detail
    {
        struct throw_with_loc
        {
            char const * const file;
            int const line;
            char const * const fn;
 
            template <class Ex>
            [[noreturn]] friend void operator+( throw_with_loc loc, Ex const & ex )
            {
                ex.load_source_location_(loc.file, loc.line, loc.fn);
                ::boost::leaf::throw_exception(ex);
            }
        };
    }
 
} }
 
////////////////////////////////////////
 
namespace boost { namespace leaf {
 
    namespace leaf_detail
    {
        inline void enforce_std_exception( std::exception const & ) noexcept { }
 
        class exception_base
        {
            std::shared_ptr<void const> auto_id_bump_;
        public:
 
            virtual error_id get_error_id() const noexcept = 0;
 
        protected:
 
            exception_base():
                auto_id_bump_(0, [](void const *) { (void) new_id(); })
            {
            }
 
            ~exception_base() noexcept { }
        };
 
        template <class Ex>
        class exception:
            public Ex,
            public exception_base,
            public error_id
        {
            error_id get_error_id() const noexcept final override
            {
                return *this;
            }
 
        public:
 
            exception( exception const & ) = default;
            exception( exception && ) = default;
 
            BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept:
                Ex(std::move(ex)),
                error_id(id)
            {
                enforce_std_exception(*this);
            }
 
            explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept:
                error_id(id)
            {
                enforce_std_exception(*this);
            }
        };
 
        template <class... T>
        struct at_least_one_derives_from_std_exception;
 
        template <>
        struct at_least_one_derives_from_std_exception<>: std::false_type { };
 
        template <class T, class... Rest>
        struct at_least_one_derives_from_std_exception<T, Rest...>
        {
            constexpr static const bool value = std::is_base_of<std::exception,T>::value || at_least_one_derives_from_std_exception<Rest...>::value;
        };
    }
 
    template <class Ex, class... E>
    inline
    typename std::enable_if<std::is_base_of<std::exception,Ex>::value, leaf_detail::exception<Ex>>::type
    exception( Ex && ex, E && ... e ) noexcept
    {
        static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
        auto id = leaf::new_error(std::forward<E>(e)...);
        return leaf_detail::exception<Ex>(id, std::forward<Ex>(ex));
    }
 
    template <class E1, class... E>
    inline
    typename std::enable_if<!std::is_base_of<std::exception,E1>::value, leaf_detail::exception<std::exception>>::type
    exception( E1 && car, E && ... cdr ) noexcept
    {
        static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
        auto id = leaf::new_error(std::forward<E1>(car), std::forward<E>(cdr)...);
        return leaf_detail::exception<std::exception>(id);
    }
 
    inline leaf_detail::exception<std::exception> exception() noexcept
    {
        return leaf_detail::exception<std::exception>(leaf::new_error());
    }
 
} }
 
#endif