MRPT  2.0.2
exceptions.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #pragma once
11 
12 #include <mrpt/core/common.h>
13 #include <mrpt/core/format.h>
14 #include <stdexcept> // logic_error
15 #include <string> // std::string, to_string()
16 #include <string_view>
17 
18 namespace mrpt::internal
19 {
20 std::string exception_line_msg(
21  const std::string_view& msg, const char* filename, unsigned int line,
22  const char* function_name);
23 
24 template <typename A, typename B>
25 inline std::string asrt_fail(
26  std::string s, A&& a, B&& b, const char* astr, const char* bstr)
27 {
28  s += "(";
29  s += astr;
30  s += ",";
31  s += bstr;
32  s += ") failed with\n";
33  s += astr;
34  s += "=";
35  s += mrpt::to_string(a);
36  s += "\n";
37  s += bstr;
38  s += "=";
39  s += mrpt::to_string(b);
40  s += "\n";
41  return s;
42 }
43 } // namespace mrpt::internal
44 
45 namespace mrpt
46 {
47 /** Builds a nice textual representation of a nested exception, which if
48  * generated using MRPT macros (THROW_EXCEPTION,...) in between
49  * MRPT_START/MRPT_END macros, will contain function names and line numbers
50  * across the call stack at the original throw point.
51  * See example of use in \ref mrpt_core_grp
52  * Uses C++11 throw_with_nested(), rethrow_if_nested().
53  * \ingroup mrpt_core_grp
54  */
55 std::string exception_to_str(const std::exception& e);
56 
57 /** \def THROW_TYPED_EXCEPTION(msg,exceptionClass) */
58 #define THROW_TYPED_EXCEPTION(msg, exceptionClass) \
59  throw exceptionClass(mrpt::internal::exception_line_msg( \
60  msg, __FILE__, __LINE__, __CURRENT_FUNCTION_NAME__))
61 
62 /** \def THROW_EXCEPTION(msg);
63  * \param msg This can be a char*, a std::string, or a literal string.
64  * Defines a unified way of reporting exceptions
65  * \sa MRPT_TRY_START, MRPT_TRY_END, THROW_EXCEPTION_FMT
66  */
67 #define THROW_EXCEPTION(msg) THROW_TYPED_EXCEPTION(msg, std::logic_error)
68 
69 #define THROW_EXCEPTION_FMT(_FORMAT_STRING, ...) \
70  THROW_EXCEPTION(mrpt::format(_FORMAT_STRING, __VA_ARGS__))
71 
72 #define THROW_TYPED_EXCEPTION_FMT(exceptionClass, _FORMAT_STRING, ...) \
73  THROW_TYPED_EXCEPTION( \
74  mrpt::format(_FORMAT_STRING, __VA_ARGS__), exceptionClass)
75 
76 /** \def THROW_STACKED_EXCEPTION
77  * \sa MRPT_TRY_START, MRPT_TRY_END
78  */
79 #define THROW_STACKED_EXCEPTION \
80  std::throw_with_nested( \
81  std::logic_error(mrpt::internal::exception_line_msg( \
82  "Called from here.", __FILE__, __LINE__, \
83  __CURRENT_FUNCTION_NAME__)))
84 
85 /** \def THROW_STACKED_EXCEPTION_CUSTOM_MSG
86  * \param e The caught exception.
87  * \param stuff Is a printf-like sequence of params, e.g: "The error happens
88  *for x=%i",x
89  */
90 #define THROW_STACKED_EXCEPTION_CUSTOM_MSG2(stuff, param1) \
91  std::throw_with_nested( \
92  std::logic_error(mrpt::internal::exception_line_msg( \
93  mrpt::format(stuff, param1), __FILE__, __LINE__, \
94  __CURRENT_FUNCTION_NAME__)))
95 
96 /** For use in CSerializable implementations */
97 #define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V) \
98  THROW_EXCEPTION(mrpt::format( \
99  "Cannot parse object: unknown serialization version number: '%i'", \
100  static_cast<int>(__V)))
101 
102 /** Defines an assertion mechanism.
103  * \note Do NOT put code that must be always executed inside this statement, but
104  * just comparisons. This is because users might require ASSERT_'s to be ignored
105  * for optimized releases.
106  * \sa MRPT_TRY_START, MRPT_TRY_END
107  */
108 #define ASSERTMSG_(f, __ERROR_MSG) \
109  do \
110  { \
111  if (!(f)) THROW_EXCEPTION(::std::string(__ERROR_MSG)); \
112  } while (0)
113 
114 /** Defines an assertion mechanism.
115  * \note Do NOT put code that must be always executed inside this statement, but
116  * just comparisons. This is because users might require ASSERT_'s to be ignored
117  * for optimized releases.
118  * \sa MRPT_TRY_START, MRPT_TRY_END
119  */
120 #define ASSERT_(f) \
121  ASSERTMSG_(f, std::string("Assert condition failed: ") + ::std::string(#f))
122 
123 /** Throws an exception if the number is NaN, IND, or +/-INF, or return the same
124  * number otherwise. */
125 #define MRPT_CHECK_NORMAL_NUMBER(v) \
126  do \
127  { \
128  ASSERT_(std::isfinite(v)); \
129  ASSERT_(!std::isnan(v)); \
130  } while (0)
131 
132 #define ASRT_FAIL(__CONDITIONSTR, __A, __B, __ASTR, __BSTR) \
133  THROW_EXCEPTION( \
134  mrpt::internal::asrt_fail(__CONDITIONSTR, __A, __B, __ASTR, __BSTR));
135 
136 /** Assert comparing two values, reporting their actual values upon failure */
137 #define ASSERT_EQUAL_(__A, __B) \
138  do \
139  { \
140  if (__A != __B) ASRT_FAIL("ASSERT_EQUAL_", __A, __B, #__A, #__B) \
141  } while (0)
142 
143 #define ASSERT_NOT_EQUAL_(__A, __B) \
144  do \
145  { \
146  if (__A == __B) ASRT_FAIL("ASSERT_NOT_EQUAL_", __A, __B, #__A, #__B) \
147  } while (0)
148 
149 #define ASSERT_BELOW_(__A, __B) \
150  do \
151  { \
152  if (__A >= __B) ASRT_FAIL("ASSERT_BELOW_", __A, __B, #__A, #__B) \
153  } while (0)
154 
155 #define ASSERT_ABOVE_(__A, __B) \
156  do \
157  { \
158  if (__A <= __B) ASRT_FAIL("ASSERT_ABOVE_", __A, __B, #__A, #__B) \
159  } while (0)
160 
161 #define ASSERT_BELOWEQ_(__A, __B) \
162  do \
163  { \
164  if (__A > __B) ASRT_FAIL("ASSERT_BELOWEQ_", __A, __B, #__A, #__B) \
165  } while (0)
166 
167 #define ASSERT_ABOVEEQ_(__A, __B) \
168  do \
169  { \
170  if (__A < __B) ASRT_FAIL("ASSERT_ABOVEEQ_", __A, __B, #__A, #__B) \
171  } while (0)
172 
173 /** Defines an assertion mechanism - only when compiled in debug.
174  * \note Do NOT put code that must be always executed inside this statement, but
175  * just comparisons. This is because users might require ASSERT_'s to be ignored
176  * for optimized releases.
177  * \sa MRPT_TRY_START, MRPT_TRY_END
178  */
179 #ifdef _DEBUG
180 #define ASSERTDEB_(f) ASSERT_(f)
181 #define ASSERTDEBMSG_(f, __ERROR_MSG) ASSERTMSG_(f, __ERROR_MSG)
182 #define ASSERTDEB_EQUAL_(__A, __B) ASSERT_EQUAL_(__A, __B)
183 #define ASSERTDEB_NOT_EQUAL_(__A, __B) ASSERT_NOT_EQUAL_(__A, __B)
184 #define ASSERTDEB_BELOW_(__A, __B) ASSERT_BELOW_(__A, __B)
185 #define ASSERTDEB_ABOVE_(__A, __B) ASSERT_ABOVE_(__A, __B)
186 #define ASSERTDEB_BELOWEQ_(__A, __B) ASSERT_BELOWEQ_(__A, __B)
187 #define ASSERTDEB_ABOVEEQ_(__A, __B) ASSERT_ABOVEEQ_(__A, __B)
188 #else
189 // clang-format off
190 #define ASSERTDEB_(f) while (0){}
191 #define ASSERTDEBMSG_(f, __ERROR_MSG) while (0){}
192 #define ASSERTDEB_EQUAL_(__A, __B) while (0){}
193 #define ASSERTDEB_NOT_EQUAL_(__A, __B) while (0){}
194 #define ASSERTDEB_BELOW_(__A, __B) while (0){}
195 #define ASSERTDEB_ABOVE_(__A, __B) while (0){}
196 #define ASSERTDEB_BELOWEQ_(__A, __B) while (0){}
197 #define ASSERTDEB_ABOVEEQ_(__A, __B) while (0){}
198 // clang-format on
199 
200 #endif
201 
202 /** The start of a standard MRPT "try...catch()" block that allows tracing throw
203  * the call stack after an exception.
204  * \sa MRPT_TRY_END,MRPT_TRY_END_WITH_CLEAN_UP
205  */
206 #define MRPT_TRY_START \
207  try \
208  {
209 /** The end of a standard MRPT "try...catch()" block that allows tracing throw
210  * the call stack after an exception.
211  * \sa MRPT_TRY_START,MRPT_TRY_END_WITH_CLEAN_UP
212  */
213 #define MRPT_TRY_END \
214  } \
215  catch (std::bad_alloc&) { throw; } \
216  catch (...) { THROW_STACKED_EXCEPTION; }
217 
218 /** The end of a standard MRPT "try...catch()" block that allows tracing throw
219  * the call stack after an exception, including a "clean up" piece of code to be
220  * run before throwing the exceptions.
221  * \sa MRPT_TRY_END,MRPT_TRY_START
222  *
223  */
224 #define MRPT_TRY_END_WITH_CLEAN_UP(stuff) \
225  } \
226  catch (std::bad_alloc&) { throw; } \
227  catch (...) { {stuff} THROW_STACKED_EXCEPTION; }
228 
229 #if MRPT_ENABLE_EMBEDDED_GLOBAL_PROFILER
230 #define MRPT_PROFILE_FUNC_START \
231  ::mrpt::system::CProfilerProxy BOOST_JOIN( \
232  __dum_var, __LINE__)(__CURRENT_FUNCTION_NAME__);
233 #else
234 #define MRPT_PROFILE_FUNC_START
235 #endif
236 
237 // General macros for use within each MRPT method/function. They provide:
238 // - Nested exception handling
239 // - Automatic profiling stats (in Debug only)
240 // ---------------------------------------------------------
241 #define MRPT_START \
242  MRPT_PROFILE_FUNC_START \
243  MRPT_TRY_START
244 
245 #define MRPT_END MRPT_TRY_END
246 
247 #define MRPT_END_WITH_CLEAN_UP(stuff) MRPT_TRY_END_WITH_CLEAN_UP(stuff)
248 } // namespace mrpt
std::string to_string(T v)
Just like std::to_string(), but with an overloaded version for std::string arguments.
Definition: format.h:36
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string exception_to_str(const std::exception &e)
Builds a nice textual representation of a nested exception, which if generated using MRPT macros (THR...
Definition: exceptions.cpp:59
std::string exception_line_msg(const std::string_view &msg, const char *filename, unsigned int line, const char *function_name)
Definition: exceptions.cpp:16
std::string asrt_fail(std::string s, A &&a, B &&b, const char *astr, const char *bstr)
Definition: exceptions.h:25



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020