Main MRPT website > C++ reference
MRPT logo
mrpt_macros.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 
29 #ifndef UTILSDEFS_H
30 #error "This file is intended for include from utils_defs.h only!"
31 #endif
32 
33 #ifndef MRPT_MACROS_H
34 #define MRPT_MACROS_H
35 
36 // A cross-compiler definition for "deprecated"-warnings
37 #if defined(__GNUC__) && (__GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2))
38  /* gcc >= 3.2 */
39 # define MRPT_DEPRECATED_PRE(_MSG)
40  // The "message" is not supported yet in GCC (JL: wait for gcc 4.4??)
41  //# define MRPT_DEPRECATED_POST(_MSG) __attribute__ ((deprecated(_MSG)))
42 # define MRPT_DEPRECATED_POST(_MSG) __attribute__ ((deprecated))
43 # elif defined(_MSC_VER) && (_MSC_VER >= 1300)
44  /* msvc >= 7 */
45 # define MRPT_DEPRECATED_PRE(_MSG) __declspec(deprecated (_MSG))
46 # define MRPT_DEPRECATED_POST(_MSG)
47 # else
48 # define MRPT_DEPRECATED_PRE(_MSG)
49 # define MRPT_DEPRECATED_POST(_MSG)
50 # endif
51 
52 /** Usage: MRPT_DECLARE_DEPRECATED_FUNCTION("Use XX instead", void myFunc(double)); */
53 #define MRPT_DECLARE_DEPRECATED_FUNCTION(__MSG, __FUNC) MRPT_DEPRECATED_PRE(__MSG) __FUNC MRPT_DEPRECATED_POST(__MSG)
54 
55 /** Declare MRPT_TODO(message) */
56 #if defined(_MSC_VER)
57  #define MRPT_DO_PRAGMA(x) __pragma(x)
58  #define __STR2__(x) #x
59  #define __STR1__(x) __STR2__(x)
60  #define __MSVCLOC__ __FILE__ "("__STR1__(__LINE__)") : "
61  #define MRPT_MSG_PRAGMA(_msg) MRPT_DO_PRAGMA(message (__MSVCLOC__ _msg))
62 #elif defined(__GNUC__)
63  #define MRPT_DO_PRAGMA(x) _Pragma (#x)
64  #define MRPT_MSG_PRAGMA(_msg) MRPT_DO_PRAGMA(message (_msg))
65 #else
66  #define MRPT_DO_PRAGMA(x)
67  #define MRPT_MSG_PRAGMA(_msg)
68 #endif
69 
70 #define MRPT_WARNING(x) MRPT_MSG_PRAGMA("Warning: " #x)
71 #define MRPT_TODO(x) MRPT_MSG_PRAGMA("TODO: " #x)
72 
73 // Define a decl. modifier for printf-like format checks at compile time:
74 #ifdef __GNUC__
75 # define MRPT_printf_format_check(_FMT_,_VARARGS_) __attribute__ ((__format__ (__printf__, _FMT_,_VARARGS_)))
76 #else
77 # define MRPT_printf_format_check(_FMT_,_VARARGS_)
78 #endif
79 // Define a decl. modifier for scanf-like format checks at compile time:
80 #ifdef __GNUC__
81 # define MRPT_scanf_format_check(_FMT_,_VARARGS_) __attribute__ ((__format__ (__scanf__, _FMT_,_VARARGS_)))
82 #else
83 # define MRPT_scanf_format_check(_FMT_,_VARARGS_)
84 #endif
85 
86 /** Used after member declarations */
87 #define MRPT_NO_THROWS throw()
88 
89 
90 // A cross-compiler definition for aligned memory structures:
91 #if defined(_MSC_VER)
92  #define MRPT_ALIGN16 __declspec(align(16))
93  #define MRPT_ALIGN32 __declspec(align(32))
94 #elif defined(__GNUC__)
95  #define MRPT_ALIGN16 __attribute__((aligned(16)))
96  #define MRPT_ALIGN32 __attribute__((aligned(32)))
97 #else
98  #define MRPT_ALIGN16
99  #define MRPT_ALIGN32
100 #endif
101 
102 /** A macro for obtaining the name of the current function: */
103 #if defined(__BORLANDC__)
104  #define __CURRENT_FUNCTION_NAME__ __FUNC__
105 #elif defined(_MSC_VER) && (_MSC_VER>=1300)
106  #define __CURRENT_FUNCTION_NAME__ __FUNCTION__
107 #elif defined(_MSC_VER) && (_MSC_VER<1300)
108  // Visual C++ 6 HAS NOT A __FUNCTION__ equivalent.
109 #define __CURRENT_FUNCTION_NAME__ ::system::extractFileName(__FILE__).c_str()
110 #else
111  #define __CURRENT_FUNCTION_NAME__ __PRETTY_FUNCTION__
112 #endif
113 
114 
115 /** \def MRPT_DEBUG_BREAKPOINT(_msg)
116  * Only if compiled in debug (_DEBUG defined), calls mrpt::system::breakpoint() with the given message.
117  * All MRPT exceptions use this macro, so mrpt::system::breakpoint() is the ideal point to set a breakpoint
118  * and catch exception before they're actually raised.
119  */
120 #ifdef _DEBUG
121 # define MRPT_DEBUG_BREAKPOINT(_msg) { mrpt::system::breakpoint(std::string(_msg)); }
122 #else
123 # define MRPT_DEBUG_BREAKPOINT(_msg) { }
124 #endif
125 
126 /** \def THROW_EXCEPTION(msg)
127  * \param msg This can be a char*, a std::string, or a literal string.
128  * Defines a unified way of reporting exceptions
129  * \sa MRPT_TRY_START, MRPT_TRY_END, THROW_EXCEPTION_CUSTOM_MSG1
130  */
131 #define THROW_EXCEPTION(msg) \
132  {\
133  std::ostringstream auxCompStr;\
134  auxCompStr << "\n\n =============== MRPT EXCEPTION =============\n";\
135  auxCompStr << __CURRENT_FUNCTION_NAME__ << ", line " << __LINE__ << ":\n";\
136  auxCompStr << msg << std::endl; \
137  auxCompStr << mrpt::system::stack_trace(); \
138  MRPT_DEBUG_BREAKPOINT(msg) \
139  throw std::logic_error( auxCompStr.str() );\
140  }\
141 
142 /** \def THROW_EXCEPTION_CUSTOM_MSG1
143  * \param e The caught exception.
144  * \param msg Is a char* or literal string.
145  */
146 #define THROW_EXCEPTION_CUSTOM_MSG1(msg,param1) \
147  {\
148  std::ostringstream auxCompStr;\
149  auxCompStr << "\n\n =============== MRPT EXCEPTION =============\n";\
150  auxCompStr << __CURRENT_FUNCTION_NAME__ << ", line " << __LINE__ << ":\n";\
151  auxCompStr << mrpt::format(msg,param1)<< std::endl; \
152  auxCompStr << mrpt::system::stack_trace(); \
153  throw std::logic_error( auxCompStr.str() );\
154  }\
155 
156 
157 /** \def THROW_TYPED_EXCEPTION(msg,exceptionClass)
158  * Defines a unified way of reporting exceptions of type different from "std::exception"
159  * \sa MRPT_TRY_START, MRPT_TRY_END
160  */
161 #define THROW_TYPED_EXCEPTION(msg,exceptionClass) \
162  {\
163  std::ostringstream auxCompStr;\
164  auxCompStr << "\n\n =============== MRPT EXCEPTION =============\n";\
165  auxCompStr << __CURRENT_FUNCTION_NAME__ << ", line " << __LINE__ << ":\n";\
166  auxCompStr << msg << std::endl; \
167  auxCompStr << mrpt::system::stack_trace(); \
168  throw exceptionClass( auxCompStr.str() );\
169  }\
170 
171 /** \def THROW_EXCEPTION_CUSTOM_MSG1
172  * \param e The caught exception.
173  * \param msg Is a char* or literal string.
174  */
175 #define THROW_TYPED_EXCEPTION_CUSTOM_MSG1(msg,param1,exceptionClass) \
176  {\
177  std::ostringstream auxCompStr;\
178  auxCompStr << "\n\n =============== MRPT EXCEPTION =============\n";\
179  auxCompStr << __CURRENT_FUNCTION_NAME__ << ", line " << __LINE__ << ":\n";\
180  auxCompStr << mrpt::format(msg,param1)<< std::endl; \
181  auxCompStr << mrpt::system::stack_trace(); \
182  throw exceptionClass( auxCompStr.str() );\
183  }\
184 
185 
186 /** \def THROW_STACKED_EXCEPTION
187  * \sa MRPT_TRY_START, MRPT_TRY_END
188  */
189 #define THROW_STACKED_EXCEPTION(e) \
190  {\
191  std::string str( e.what() );\
192  if (str.find("MRPT stack trace")==std::string::npos) \
193  { \
194  str+= __CURRENT_FUNCTION_NAME__;\
195  str+= mrpt::format(", line %i:\n", __LINE__ );\
196  if (str.size()>3000) { std::cerr << "TOO MANY STACKED EXCEPTIONS!: " << std::endl << str << std::endl; abort(); } \
197  throw std::logic_error( str );\
198  } \
199  else throw std::logic_error( e.what() );\
200  }\
201 
202 /** \def THROW_STACKED_EXCEPTION_CUSTOM_MSG
203  * \param e The caught exception.
204  * \param msg Is a char* or std::string.
205  */
206 #define THROW_STACKED_EXCEPTION_CUSTOM_MSG1(e,msg) \
207  {\
208  std::ostringstream auxCompStr;\
209  auxCompStr << e.what() ; \
210  auxCompStr << msg << std::endl; \
211  throw std::logic_error( auxCompStr.str() );\
212  }\
213 
214 /** \def THROW_STACKED_EXCEPTION_CUSTOM_MSG
215  * \param e The caught exception.
216  * \param stuff Is a printf-like sequence of params, e.g: "The error happens for x=%i",x
217  */
218 #define THROW_STACKED_EXCEPTION_CUSTOM_MSG2(e,stuff,param1) \
219  {\
220  std::ostringstream auxCompStr;\
221  auxCompStr << e.what() ; \
222  auxCompStr << mrpt::format( stuff, param1 ) << std::endl; \
223  throw std::logic_error( auxCompStr.str() );\
224  }\
225 
226 /** For use in CSerializable implementations */
227 #define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(V) THROW_EXCEPTION(mrpt::format("Cannot parse object: unknown serialization version number: '%i'",static_cast<int>(version)))
228 
229 
230 #if MRPT_HAS_ASSERT
231  /** Defines an assertion mechanism.
232  * \note Do NOT put code that must be always executed inside this statement, but just comparisons. This is because users might require ASSERT_'s to be ignored for optimized releases.
233  * \sa MRPT_TRY_START, MRPT_TRY_END
234  */
235 # define ASSERTMSG_(f,__ERROR_MSG) \
236  { \
237  if (!(f)) THROW_EXCEPTION( ::std::string( __ERROR_MSG ) ); \
238  }
239 
240  /** Defines an assertion mechanism.
241  * \note Do NOT put code that must be always executed inside this statement, but just comparisons. This is because users might require ASSERT_'s to be ignored for optimized releases.
242  * \sa MRPT_TRY_START, MRPT_TRY_END
243  */
244 # define ASSERT_(f) \
245  ASSERTMSG_(f, std::string("Assert condition failed: ") + ::std::string(#f) )
246 
247 /** Throws an exception if the number is NaN, IND, or +/-INF, or return the same number otherwise.
248  */
249 #define MRPT_CHECK_NORMAL_NUMBER(v) \
250  { \
251  if (math::isNaN(v)) THROW_EXCEPTION("Check failed (value is NaN)"); \
252  if (!math::isFinite(v)) THROW_EXCEPTION("Check failed (value is not finite)"); \
253  }
254 
255  // The following macro is based on dclib:
256  // Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
257  // License: Boost Software License See LICENSE.txt for the full license.
258  namespace mrpt
259  {
260  namespace utils
261  {
262  template <bool value> struct compile_time_assert;
263  template <> struct compile_time_assert<true> { enum {value=1}; };
264  }
265  }
266  #define MRPT_COMPILE_TIME_ASSERT(expression) \
267  typedef char BOOST_JOIN(MRPT_CTA, __LINE__)[::mrpt::utils::compile_time_assert<(bool)(expression)>::value];
268 
269  /** Assert comparing two values, reporting their actual values upon failure */
270  #define ASSERT_EQUAL_( __A, __B) { if (__A!=__B) { std::ostringstream s;s<<"ASSERT_EQUAL_("<<#__A<<","<<#__B<<") failed with\n"<<#__A<<"=" <<__A <<"\n"<<#__B<<"="<<__B; THROW_EXCEPTION(s.str()) } }
271  #define ASSERT_NOT_EQUAL_( __A, __B) { if (__A==__B) { std::ostringstream s;s<<"ASSERT_NOT_EQUAL_("<<#__A<<","<<#__B<<") failed with\n"<<#__A<<"=" <<__A <<"\n"<<#__B<<"="<<__B; THROW_EXCEPTION(s.str()) } }
272  #define ASSERT_BELOW_( __A, __B) { if (__A>=__B) { std::ostringstream s;s<<"ASSERT_BELOW_("<<#__A<<","<<#__B<<") failed with\n"<<#__A<<"=" <<__A <<"\n"<<#__B<<"="<<__B; THROW_EXCEPTION(s.str()) } }
273  #define ASSERT_ABOVE_( __A, __B) { if (__A<=__B) { std::ostringstream s;s<<"ASSERT_ABOVE_("<<#__A<<","<<#__B<<") failed with\n"<<#__A<<"=" <<__A <<"\n"<<#__B<<"="<<__B; THROW_EXCEPTION(s.str()) } }
274  #define ASSERT_BELOWEQ_( __A, __B) { if (__A>__B) { std::ostringstream s;s<<"ASSERT_BELOWEQ_("<<#__A<<","<<#__B<<") failed with\n"<<#__A<<"=" <<__A <<"\n"<<#__B<<"="<<__B; THROW_EXCEPTION(s.str()) } }
275  #define ASSERT_ABOVEEQ_( __A, __B) { if (__A<__B) { std::ostringstream s;s<<"ASSERT_ABOVEEQ_("<<#__A<<","<<#__B<<") failed with\n"<<#__A<<"=" <<__A <<"\n"<<#__B<<"="<<__B; THROW_EXCEPTION(s.str()) } }
276 
277  #define ASSERT_FILE_EXISTS_(FIL) ASSERTMSG_( mrpt::system::fileExists(FIL), std::string("Assert file existence failed: ") + ::std::string(FIL) )
278  #define ASSERT_DIRECTORY_EXISTS_(DIR) ASSERTMSG_( mrpt::system::directoryExists(DIR), std::string("Assert directory existence failed: ") + ::std::string(DIR) )
279 
280 #else // MRPT_HAS_ASSERT
281 # define ASSERTMSG_(f,__ERROR_MSG) { }
282 # define ASSERT_(f) { }
283 # define MRPT_CHECK_NORMAL_NUMBER(val) { }
284 # define MRPT_COMPILE_TIME_ASSERT(f) { }
285 # define ASSERT_EQUAL_( __A, __B) { }
286 # define ASSERT_NOT_EQUAL_( __A, __B) { }
287 # define ASSERT_BELOW_( __A, __B) { }
288 # define ASSERT_ABOVE_( __A, __B) { }
289 # define ASSERT_BELOWEQ_( __A, __B) { }
290 # define ASSERT_ABOVEEQ_( __A, __B) { }
291 
292 # define ASSERT_FILE_EXISTS_(FIL) { }
293 # define ASSERT_DIRECTORY_EXISTS_(DIR) { }
294 #endif // MRPT_HAS_ASSERT
295 
296 /** Defines an assertion mechanism - only when compiled in debug.
297  * \note Do NOT put code that must be always executed inside this statement, but just comparisons. This is because users might require ASSERT_'s to be ignored for optimized releases.
298  * \sa MRPT_TRY_START, MRPT_TRY_END
299  */
300 #ifdef _DEBUG
301 # define ASSERTDEB_(f) ASSERT_(f)
302 # define ASSERTDEBMSG_(f,__ERROR_MSG) ASSERTMSG_(f,__ERROR_MSG)
303 #else
304 # define ASSERTDEB_(f) { }
305 # define ASSERTDEBMSG_(f,__ERROR_MSG) { }
306 #endif
307 
308 
309 /** Can be used to avoid "not used parameters" warnings from the compiler
310  */
311 #define MRPT_UNUSED_PARAM(a) (void)(a)
312 
313 #if MRPT_HAS_STACKED_EXCEPTIONS
314  /** The start of a standard MRPT "try...catch()" block that allows tracing throw the call stack after an exception.
315  * \sa MRPT_TRY_END,MRPT_TRY_END_WITH_CLEAN_UP
316  */
317 # define MRPT_TRY_START \
318  try { \
319 
320  /** The end of a standard MRPT "try...catch()" block that allows tracing throw the call stack after an exception.
321  * \sa MRPT_TRY_START,MRPT_TRY_END_WITH_CLEAN_UP
322  */
323 # define MRPT_TRY_END \
324  } \
325  catch (std::bad_alloc &) \
326  { throw; } \
327  catch (std::exception &e) \
328  { \
329  THROW_STACKED_EXCEPTION(e); \
330  } \
331  catch (...) \
332  { \
333  THROW_EXCEPTION("Unexpected runtime error!"); \
334  } \
335 
336  /** The end of a standard MRPT "try...catch()" block that allows tracing throw the call stack after an exception, including a "clean up" piece of code to be run before throwing the exceptions.
337  * \sa MRPT_TRY_END,MRPT_TRY_START
338  */
339 # define MRPT_TRY_END_WITH_CLEAN_UP(stuff) \
340  } \
341  catch (std::bad_alloc &) \
342  { throw; } \
343  catch (std::exception &e) \
344  { \
345  {stuff} \
346  THROW_STACKED_EXCEPTION(e); \
347  } \
348  catch (...) \
349  { \
350  { stuff } \
351  THROW_EXCEPTION("Unexpected runtime error!"); \
352  } \
353 
354 #else
355 # define MRPT_TRY_START
356 # define MRPT_TRY_END
357 # define MRPT_TRY_END_WITH_CLEAN_UP(stuff)
358 #endif
359 
360 #if MRPT_ENABLE_EMBEDDED_GLOBAL_PROFILER
361 # define MRPT_PROFILE_FUNC_START ::mrpt::utils::CProfilerProxy BOOST_JOIN(__dum_var,__LINE__)( __CURRENT_FUNCTION_NAME__);
362 #else
363 # define MRPT_PROFILE_FUNC_START
364 #endif
365 
366 // General macros for use within each MRPT method/function. They provide:
367 // - Nested exception handling
368 // - Automatic profiling stats (in Debug only)
369 // ---------------------------------------------------------
370 #define MRPT_START \
371  MRPT_PROFILE_FUNC_START \
372  MRPT_TRY_START
373 
374 #define MRPT_END \
375  MRPT_TRY_END
376 
377 #define MRPT_END_WITH_CLEAN_UP(stuff) \
378  MRPT_TRY_END_WITH_CLEAN_UP(stuff)
379 
380 // Generic constants and defines:
381 // ---------------------------------------------------------
382 #ifndef M_PI
383 # define M_PI 3.14159265358979323846264338327950288 // PI constant
384 #endif
385 
386 #ifndef M_2PI
387 # define M_2PI 6.283185307179586476925286766559 // The 2*PI constant
388 #endif
389 
390 #define M_PIf 3.14159265358979f
391 #define M_2PIf 6.28318530717959f
392 
393 #if defined(HAVE_LONG_DOUBLE) && !defined(M_PIl)
394 # define M_PIl 3.14159265358979323846264338327950288L
395 # define M_2PIl (2.0L*3.14159265358979323846264338327950288L)
396 #endif
397 
398 
399 // Define a decl. modifier for printf-like format checks at compile time:
400 #ifdef __GNUC__
401 # define MRPT_printf_format_check(_FMT_,_VARARGS_) __attribute__ ((__format__ (__printf__, _FMT_,_VARARGS_)))
402 #else
403 # define MRPT_printf_format_check(_FMT_,_VARARGS_)
404 #endif
405 
406 // Define a decl. modifier for scanf-like format checks at compile time:
407 #ifdef __GNUC__
408 # define MRPT_scanf_format_check(_FMT_,_VARARGS_) __attribute__ ((__format__ (__scanf__, _FMT_,_VARARGS_)))
409 #else
410 # define MRPT_scanf_format_check(_FMT_,_VARARGS_)
411 #endif
412 
413 
414 /** Used after member declarations */
415 #define MRPT_NO_THROWS throw()
416 
417 /** Tells the compiler we really want to inline that function */
418 #if (defined _MSC_VER) || (defined __INTEL_COMPILER)
419 #define MRPT_FORCE_INLINE __forceinline
420 #else
421 #define MRPT_FORCE_INLINE inline
422 #endif
423 
424 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013