nested_exception.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Nested Exception support header (nested_exception class) for -*- C++ -*-
  2. // Copyright (C) 2009-2018 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/nested_exception.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{exception}
  23. */
  24. #ifndef _GLIBCXX_NESTED_EXCEPTION_H
  25. #define _GLIBCXX_NESTED_EXCEPTION_H 1
  26. #pragma GCC visibility push(default)
  27. #if __cplusplus < 201103L
  28. # include <bits/c++0x_warning.h>
  29. #else
  30. #include <bits/c++config.h>
  31. #include <bits/move.h>
  32. extern "C++" {
  33. namespace std
  34. {
  35. /**
  36. * @addtogroup exceptions
  37. * @{
  38. */
  39. /// Exception class with exception_ptr data member.
  40. class nested_exception
  41. {
  42. exception_ptr _M_ptr;
  43. public:
  44. nested_exception() noexcept : _M_ptr(current_exception()) { }
  45. nested_exception(const nested_exception&) noexcept = default;
  46. nested_exception& operator=(const nested_exception&) noexcept = default;
  47. virtual ~nested_exception() noexcept;
  48. [[noreturn]]
  49. void
  50. rethrow_nested() const
  51. {
  52. if (_M_ptr)
  53. rethrow_exception(_M_ptr);
  54. std::terminate();
  55. }
  56. exception_ptr
  57. nested_ptr() const noexcept
  58. { return _M_ptr; }
  59. };
  60. template<typename _Except>
  61. struct _Nested_exception : public _Except, public nested_exception
  62. {
  63. explicit _Nested_exception(const _Except& __ex)
  64. : _Except(__ex)
  65. { }
  66. explicit _Nested_exception(_Except&& __ex)
  67. : _Except(static_cast<_Except&&>(__ex))
  68. { }
  69. };
  70. // [except.nested]/8
  71. // Throw an exception of unspecified type that is publicly derived from
  72. // both remove_reference_t<_Tp> and nested_exception.
  73. template<typename _Tp>
  74. [[noreturn]]
  75. inline void
  76. __throw_with_nested_impl(_Tp&& __t, true_type)
  77. {
  78. using _Up = typename remove_reference<_Tp>::type;
  79. throw _Nested_exception<_Up>{std::forward<_Tp>(__t)};
  80. }
  81. template<typename _Tp>
  82. [[noreturn]]
  83. inline void
  84. __throw_with_nested_impl(_Tp&& __t, false_type)
  85. { throw std::forward<_Tp>(__t); }
  86. /// If @p __t is derived from nested_exception, throws @p __t.
  87. /// Else, throws an implementation-defined object derived from both.
  88. template<typename _Tp>
  89. [[noreturn]]
  90. inline void
  91. throw_with_nested(_Tp&& __t)
  92. {
  93. using _Up = typename decay<_Tp>::type;
  94. using _CopyConstructible
  95. = __and_<is_copy_constructible<_Up>, is_move_constructible<_Up>>;
  96. static_assert(_CopyConstructible::value,
  97. "throw_with_nested argument must be CopyConstructible");
  98. using __nest = __and_<is_class<_Up>, __bool_constant<!__is_final(_Up)>,
  99. __not_<is_base_of<nested_exception, _Up>>>;
  100. std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{});
  101. }
  102. // Determine if dynamic_cast<const nested_exception&> would be well-formed.
  103. template<typename _Tp>
  104. using __rethrow_if_nested_cond = typename enable_if<
  105. __and_<is_polymorphic<_Tp>,
  106. __or_<__not_<is_base_of<nested_exception, _Tp>>,
  107. is_convertible<_Tp*, nested_exception*>>>::value
  108. >::type;
  109. // Attempt dynamic_cast to nested_exception and call rethrow_nested().
  110. template<typename _Ex>
  111. inline __rethrow_if_nested_cond<_Ex>
  112. __rethrow_if_nested_impl(const _Ex* __ptr)
  113. {
  114. if (auto __ne_ptr = dynamic_cast<const nested_exception*>(__ptr))
  115. __ne_ptr->rethrow_nested();
  116. }
  117. // Otherwise, no effects.
  118. inline void
  119. __rethrow_if_nested_impl(const void*)
  120. { }
  121. /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested().
  122. template<typename _Ex>
  123. inline void
  124. rethrow_if_nested(const _Ex& __ex)
  125. { std::__rethrow_if_nested_impl(std::__addressof(__ex)); }
  126. // @} group exceptions
  127. } // namespace std
  128. } // extern "C++"
  129. #endif // C++11
  130. #pragma GCC visibility pop
  131. #endif // _GLIBCXX_NESTED_EXCEPTION_H