3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_ASSERT_H
20 #define LEMON_ASSERT_H
22 /// \ingroup exceptions
24 /// \brief Extended assertion handling
26 #include <lemon/error.h>
33 class AssertionFailedError : public LogicError {
35 const char *_assertion;
38 const char *_function;
41 mutable ExceptionMember<std::string> _message_holder;
44 AssertionFailedError(const char *file, int line, const char *function,
45 const char *msg, const char *assertion = 0) :
46 _assertion(assertion), _file(file), _line(line),
47 _function(function), _message(msg) {}
50 const char* assertion() const { return _assertion; }
52 const char* message() const { return _message; }
54 const char* file() const { return _file; }
56 const char* function() const { return _function; }
58 int line() const { return _line; }
61 virtual const char* what() const throw() {
63 std::ostringstream ostr;
64 ostr << _file << ":" << _line << ": ";
66 ostr << _function << ": ";
69 ostr << " (assertion '" << _assertion << "' failed)";
70 _message_holder.set(ostr.str());
71 return ostr.str().c_str();
74 if( _message_holder.valid() ) return _message_holder.get().c_str();
75 return "lemon::AssertionFailedError";
77 virtual ~AssertionFailedError() throw() {}
81 inline void assert_fail_log(const char *file, int line,
83 const std::exception& exception,
84 const char *assertion)
86 std::cerr << file << ":" << line << ": ";
88 std::cerr << function << ": ";
89 std::cerr << exception.what();
91 std::cerr << " (assertion '" << assertion << "' failed)";
92 std::cerr << std::endl;
95 inline void assert_fail_log(const char *file, int line, const char *function,
96 const char *message, const char *assertion)
98 std::cerr << file << ":" << line << ": ";
100 std::cerr << function << ": ";
101 std::cerr << message;
103 std::cerr << " (assertion '" << assertion << "' failed)";
104 std::cerr << std::endl;
107 inline void assert_fail_log(const char *file, int line, const char *function,
108 const std::string& message, const char *assertion)
110 assert_fail_log(file, line, function, message.c_str(), assertion);
113 inline void assert_fail_abort(const char *file, int line,
114 const char *function,
115 const std::exception& exception,
116 const char *assertion)
118 std::cerr << file << ":" << line << ": ";
120 std::cerr << function << ": ";
121 std::cerr << exception.what();
123 std::cerr << " (assertion '" << assertion << "' failed)";
124 std::cerr << std::endl;
128 inline void assert_fail_abort(const char *file, int line,
129 const char *function, const char* message,
130 const char *assertion)
132 std::cerr << file << ":" << line << ": ";
134 std::cerr << function << ": ";
135 std::cerr << message;
137 std::cerr << " (assertion '" << assertion << "' failed)";
138 std::cerr << std::endl;
142 inline void assert_fail_abort(const char *file, int line,
143 const char *function,
144 const std::string& message,
145 const char *assertion)
147 assert_fail_abort(file, line, function, message.c_str(), assertion);
150 inline void assert_fail_error(const char *file, int line,
151 const char *function,
152 const std::exception& exception,
153 const char *assertion)
155 throw AssertionFailedError(file, line, function,
156 exception.what(), assertion);
159 inline void assert_fail_error(const char *file, int line,
160 const char *function, const char *message,
161 const char *assertion)
163 throw AssertionFailedError(file, line, function, message, assertion);
166 inline void assert_fail_error(const char *file, int line,
167 const char *function,
168 const std::string& message,
169 const char *assertion)
171 assert_fail_error(file, line, function, message.c_str(), assertion);
174 template <typename Exception>
175 inline void assert_fail_exception(const char *, int, const char *,
176 const Exception& exception,
177 const char *, const std::exception* =
178 static_cast<const Exception*>(0))
183 inline void assert_fail_exception(const char *file, int line,
184 const char *function, const char *message,
185 const char *assertion)
187 throw AssertionFailedError(file, line, function, message, assertion);
190 inline void assert_fail_exception(const char *file, int line,
191 const char *function,
192 const std::string& message,
193 const char *assertion)
195 assert_fail_exception(file, line, function, message.c_str(), assertion);
201 #endif // LEMON_ASSERT_H
206 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \
207 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
208 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \
209 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \
210 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
211 #error "Lemon assertion system is not set properly"
214 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \
215 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
216 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \
217 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \
218 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \
219 defined(LEMON_ENABLE_ASSERT)) && \
220 defined(LEMON_DISABLE_ASSERTS)
221 #error "Lemon assertion system is not set properly"
225 #if defined LEMON_ASSERT_LOG
226 # undef LEMON_ASSERT_HANDLER
227 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log
228 #elif defined LEMON_ASSERT_ABORT
229 # undef LEMON_ASSERT_HANDLER
230 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
231 #elif defined LEMON_ASSERT_ERROR
232 # undef LEMON_ASSERT_HANDLER
233 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
234 #elif defined LEMON_ASSERT_EXCEPTION
235 # undef LEMON_ASSERT_HANDLER
236 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
237 #elif defined LEMON_ASSERT_CUSTOM
238 # undef LEMON_ASSERT_HANDLER
239 # ifndef LEMON_CUSTOM_ASSERT_HANDLER
240 # error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
242 # define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
243 #elif defined LEMON_ENABLE_ASSERTS
244 # undef LEMON_ASSERT_HANDLER
245 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
247 # undef LEMON_ASSERT_HANDLER
251 #ifndef LEMON_FUNCTION_NAME
252 # define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
257 /// \ingroup exceptions
259 /// \brief Macro for assertions with customizable message
261 /// Macro for assertions with customizable message.
262 /// \param exp An expression convertible to bool. If the expression is
263 /// false, then an assertion is raised. The concrete behaviour depends
264 /// on the settings of the assertion system.
265 /// \param msg A \e const \e char*, a \e const std::string& or a \e
266 /// const \e std::exception& parameter. The variable can be used to
267 /// provide information about the circumstances of failed assertion.
269 /// The assertions are disabled in the default behaviour. You can
270 /// enable the assertions with the following code:
272 /// #define LEMON_ENABLE_ASSERTS
274 /// or with compilation parameters:
276 /// g++ -DLEMON_ENABLE_ASSERTS
277 /// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
280 /// The %lemon assertion system has a wide range of customization
281 /// properties. As default behaviour the failed assertion prints a
282 /// short log message to the standard ouput and aborts the execution.
284 /// The following modes can be used in the assertion system:
286 /// - \e LEMON_ASSERT_LOG The failed assert print a short convenient
287 /// error message to the standard error and continues the
289 /// - \e LEMON_ASSERT_ABORT This mode is similar to the \e
290 /// LEMON_ASSERT_LOG, but it aborts the program. It is the default
291 /// operation mode when the asserts are enabled with \e
292 /// LEMON_ENABLE_ASSERTS.
293 /// - \e LEMON_ASSERT_ERROR The assert throws an \ref
294 /// lemon::AssertionFailedError "AssertionFailedError". If the \c
295 /// msg parameter is an exception, then the result of the \ref
296 /// lemon::Exception::what() "what()" member function is passed as
298 /// - \e LEMON_ASSERT_EXCEPTION If the specified \c msg is an
299 /// exception then it raised directly (solving that the exception
300 /// can not be thrown polymorphically), otherwise an \ref
301 /// lemon::AssertionFailedError "AssertionFailedError" is thrown with
302 /// the given parameter.
303 /// - \e LEMON_ASSERT_CUSTOM The user can define an own assertion
304 /// handler functions. Three overloaded functions should be defined
305 /// with the following parameter lists:
307 /// void custom_assert_handler(const char* file, int line,
308 /// const char* function, const char* message, const char* expression);
309 /// void custom_assert_handler(const char* file, int line,
310 /// const char* function, const std::string& message, const char* expression);
311 /// void custom_assert_handler(const char* file, int line,
312 /// const char* function, const std::exception& message, const char* expression);
314 /// The name of the functions should be defined as the \c
315 /// LEMON_CUSTOM_ASSERT_HANDLER macro name.
317 /// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
319 /// Whenever an assertion is occured, one of the custom assertion
320 /// handler is called with appropiate parameters.
322 /// The assertion mode can be changed within one compilation unit, if
323 /// the macros are redefined with other settings and the
324 /// lemon/assert.h file is reincluded then the behaviour is changed
325 /// appropiately to the new settings.
326 # define LEMON_ASSERT(exp, msg) \
327 (static_cast<void> (!!(exp) ? 0 : ( \
328 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
329 LEMON_FUNCTION_NAME, \
333 /// \ingroup exceptions
335 /// \brief Macro for mark not yet implemented features.
337 /// Macro for mark not yet implemented features and outstanding bugs.
338 /// It is close to be the shortcut of the following code:
340 /// LEMON_ASSERT(false, msg);
342 # define LEMON_FIXME(msg) \
343 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \
344 "FIXME: " msg, static_cast<const char*>(0)))
348 # ifndef LEMON_ASSERT_HANDLER
349 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0))
350 # define LEMON_FIXME(msg) (static_cast<void>(0))
352 # define LEMON_ASSERT(exp, msg) \
353 (static_cast<void> (!!(exp) ? 0 : ( \
354 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
355 LEMON_FUNCTION_NAME, \
357 # define LEMON_FIXME(msg) \
358 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \
359 "FIXME: " msg, static_cast<const char*>(0)))