exception.hpp 5.3 KB

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