exceptions.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*=============================================================================
  2. Copyright (c) 2005-2007 Dan Marsden
  3. Copyright (c) 2005-2007 Joel de Guzman
  4. Copyright (c) 2015 John Fletcher
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ==============================================================================*/
  8. #include <stdexcept>
  9. #include <string>
  10. #include <boost/phoenix/core.hpp>
  11. #include <boost/phoenix/operator.hpp>
  12. #include <boost/phoenix/statement.hpp>
  13. #include <boost/phoenix/scope/local_variable.hpp>
  14. #include <boost/phoenix/bind/bind_member_function.hpp>
  15. #include <boost/detail/lightweight_test.hpp>
  16. struct base_exception : std::exception
  17. {
  18. explicit
  19. base_exception(char const *msg)
  20. : _sliced(true), _what(msg)
  21. {}
  22. base_exception(base_exception const &other)
  23. : _sliced(true), _what(other._what)
  24. {
  25. }
  26. char const *what() const BOOST_NOEXCEPT_OR_NOTHROW
  27. {
  28. if (_sliced) { return "sliced ..."; }
  29. return _what;
  30. }
  31. bool _sliced;
  32. char const *_what;
  33. };
  34. struct extended_exception : base_exception
  35. {
  36. explicit
  37. extended_exception(char const *msg)
  38. : base_exception(msg)
  39. {
  40. // mark as not sliced
  41. _sliced = false;
  42. }
  43. extended_exception(extended_exception const &other)
  44. : base_exception(other)
  45. {
  46. // mark as not sliced
  47. _sliced = false;
  48. }
  49. };
  50. int main()
  51. {
  52. using boost::phoenix::throw_;
  53. using boost::phoenix::try_;
  54. using boost::phoenix::ref;
  55. using boost::phoenix::local_names::_e;
  56. using boost::phoenix::bind;
  57. using std::exception;
  58. using std::string;
  59. using std::runtime_error;
  60. namespace phx = boost::phoenix;
  61. {
  62. try
  63. {
  64. throw_(runtime_error("error"))();
  65. BOOST_ERROR("exception should have been thrown");
  66. }
  67. catch(runtime_error& err)
  68. {
  69. BOOST_TEST(err.what() == string("error"));
  70. }
  71. }
  72. {
  73. try
  74. {
  75. try
  76. {
  77. throw runtime_error("error");
  78. }
  79. catch(exception&)
  80. {
  81. throw_()();
  82. BOOST_ERROR("exception should have been rethrown");
  83. }
  84. }
  85. catch(exception& err)
  86. {
  87. BOOST_TEST(err.what() == string("error"));
  88. }
  89. }
  90. {
  91. bool caught_exception = false;
  92. try_
  93. [ throw_(runtime_error("error")) ]
  94. .catch_<exception>(_e) // captured but unused
  95. [
  96. ref(caught_exception) = true
  97. ]();
  98. BOOST_TEST(caught_exception);
  99. }
  100. {
  101. bool caught_exception = false;
  102. string what;
  103. try_
  104. [ throw_(runtime_error("error")) ]
  105. .catch_<exception>(_e)
  106. [
  107. ref(caught_exception) = true
  108. // ambiguous with std::ref
  109. , phx::ref(what) = phx::bind(&exception::what, _e)
  110. ]();
  111. BOOST_TEST(caught_exception);
  112. BOOST_TEST(what == string("error"));
  113. }
  114. {
  115. bool caught_exception = false;
  116. string what;
  117. try_
  118. [ throw_(extended_exception("error")) ]
  119. .catch_<base_exception>(_e) // A thrown object should not be copied due to slicing.
  120. [
  121. ref(caught_exception) = true
  122. // ambiguous with std::ref
  123. , phx::ref(what) = phx::bind(&exception::what, _e)
  124. ]();
  125. BOOST_TEST(caught_exception);
  126. BOOST_TEST(what == string("error"));
  127. }
  128. {
  129. bool caught_exception = false;
  130. try_
  131. [ throw_(runtime_error("error")) ]
  132. .catch_all
  133. [ ref(caught_exception) = true ]();
  134. BOOST_TEST(caught_exception);
  135. }
  136. {
  137. bool caught_correct_exception = false;
  138. string what;
  139. try_
  140. [ throw_(runtime_error("error")) ]
  141. .catch_<string>()
  142. [ ref(caught_correct_exception) = false ]
  143. .catch_<exception>(_e)
  144. [
  145. ref(caught_correct_exception) = true
  146. // ambiguous with std::ref
  147. , phx::ref(what) = phx::bind(&exception::what, _e)
  148. ]();
  149. BOOST_TEST(caught_correct_exception);
  150. BOOST_TEST(what == string("error"));
  151. }
  152. {
  153. bool caught_correct_exception = false;
  154. try_
  155. [ throw_(runtime_error("error")) ]
  156. .catch_<string>()
  157. [ ref(caught_correct_exception) = false ]
  158. .catch_all
  159. [ ref(caught_correct_exception) = true]();
  160. BOOST_TEST(caught_correct_exception);
  161. }
  162. return boost::report_errors();
  163. }