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