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 assert_fail_log(file, line, function, exception, assertion);
122 inline void assert_fail_abort(const char *file, int line,
123 const char *function, const char* message,
124 const char *assertion)
126 assert_fail_log(file, line, function, message, assertion);
130 inline void assert_fail_abort(const char *file, int line,
131 const char *function,
132 const std::string& message,
133 const char *assertion)
135 assert_fail_log(file, line, function, message.c_str(), assertion);
139 inline void assert_fail_error(const char *file, int line,
140 const char *function,
141 const std::exception& exception,
142 const char *assertion)
144 throw AssertionFailedError(file, line, function,
145 exception.what(), assertion);
148 inline void assert_fail_error(const char *file, int line,
149 const char *function, const char *message,
150 const char *assertion)
152 throw AssertionFailedError(file, line, function, message, assertion);
155 inline void assert_fail_error(const char *file, int line,
156 const char *function,
157 const std::string& message,
158 const char *assertion)
160 throw AssertionFailedError(file, line, function, message.c_str(), assertion);
163 template <typename Exception>
164 inline void assert_fail_exception(const char *, int, const char *,
165 const Exception& exception,
166 const char *, const std::exception* =
167 static_cast<const Exception*>(0))
172 inline void assert_fail_exception(const char *file, int line,
173 const char *function, const char *message,
174 const char *assertion)
176 throw AssertionFailedError(file, line, function, message, assertion);
179 inline void assert_fail_exception(const char *file, int line,
180 const char *function,
181 const std::string& message,
182 const char *assertion)
184 throw AssertionFailedError(file, line, function, message.c_str(), assertion);
190 #endif // LEMON_ASSERT_H
195 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \
196 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
197 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \
198 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \
199 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
200 #error "LEMON assertion system is not set properly"
203 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \
204 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
205 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \
206 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \
207 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \
208 defined(LEMON_ENABLE_ASSERTS)) && \
209 defined(LEMON_DISABLE_ASSERTS)
210 #error "LEMON assertion system is not set properly"
214 #if defined LEMON_ASSERT_LOG
215 # undef LEMON_ASSERT_HANDLER
216 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log
217 #elif defined LEMON_ASSERT_ABORT
218 # undef LEMON_ASSERT_HANDLER
219 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
220 #elif defined LEMON_ASSERT_ERROR
221 # undef LEMON_ASSERT_HANDLER
222 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
223 #elif defined LEMON_ASSERT_EXCEPTION
224 # undef LEMON_ASSERT_HANDLER
225 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
226 #elif defined LEMON_ASSERT_CUSTOM
227 # undef LEMON_ASSERT_HANDLER
228 # ifndef LEMON_CUSTOM_ASSERT_HANDLER
229 # error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
231 # define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
232 #elif defined LEMON_ENABLE_ASSERTS
233 # undef LEMON_ASSERT_HANDLER
234 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
236 # undef LEMON_ASSERT_HANDLER
240 #ifndef LEMON_FUNCTION_NAME
241 # define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
246 /// \ingroup exceptions
248 /// \brief Macro for assertion with customizable message
250 /// Macro for assertion with customizable message.
251 /// \param exp An expression that must be convertible to \c bool.
252 /// If it is \c false, then an assertion is raised. The concrete
253 /// behaviour depends on the settings of the assertion system.
254 /// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or
255 /// a <tt>const std::exception&</tt> parameter, which can be used to
256 /// provide information about the circumstances of the failed assertion.
258 /// The assertions are disabled in the default behaviour.
259 /// You can enable them with the following code:
261 /// #define LEMON_ENABLE_ASSERTS
263 /// or with compilation parameters:
265 /// g++ -DLEMON_ENABLE_ASSERTS
266 /// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
269 /// The LEMON assertion system has a wide range of customization
270 /// properties. As a default behaviour the failed assertion prints a
271 /// short log message to the standard error and aborts the execution.
273 /// The following modes can be used in the assertion system:
275 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
276 /// message to the standard error and continues the execution.
277 /// - \c LEMON_ASSERT_ABORT This mode is similar to the
278 /// \c LEMON_ASSERT_LOG, but it aborts the program. It is the default
279 /// behaviour mode when the assertions are enabled with
280 /// \c LEMON_ENABLE_ASSERTS.
281 /// - \c LEMON_ASSERT_ERROR The assertion throws an
282 /// \ref lemon::AssertionFailedError "AssertionFailedError".
283 /// If the \c msg parameter is an exception, then the result of the
284 /// \ref lemon::Exception::what() "what()" member function is passed
285 /// as error message.
286 /// - \c LEMON_ASSERT_EXCEPTION If the specified \c msg is an
287 /// exception, then it raised directly (solving that the exception
288 /// can not be thrown polymorphically), otherwise an \ref
289 /// lemon::AssertionFailedError "AssertionFailedError" is thrown with
290 /// the given parameters.
291 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
292 /// functions. Three overloaded functions should be defined with the
293 /// following parameter lists:
295 /// void custom_assert_handler(const char* file, int line, const char* function,
296 /// const char* message, const char* assertion);
297 /// void custom_assert_handler(const char* file, int line, const char* function,
298 /// const std::string& message, const char* assertion);
299 /// void custom_assert_handler(const char* file, int line, const char* function,
300 /// const std::exception& message, const char* assertion);
302 /// The name of the functions should be defined as the \c
303 /// LEMON_CUSTOM_ASSERT_HANDLER macro name.
305 /// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
307 /// Whenever an assertion is occured, one of the custom assertion
308 /// handlers is called with appropiate parameters.
310 /// The assertion mode can also be changed within one compilation unit.
311 /// If the macros are redefined with other settings and the
312 /// \ref lemon/assert.h "assert.h" file is reincluded, then the
313 /// behaviour is changed appropiately to the new settings.
314 # define LEMON_ASSERT(exp, msg) \
315 (static_cast<void> (!!(exp) ? 0 : ( \
316 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
317 LEMON_FUNCTION_NAME, \
321 /// \ingroup exceptions
323 /// \brief Macro for mark not yet implemented features.
325 /// Macro for mark not yet implemented features and outstanding bugs.
326 /// It is close to be the shortcut of the following code:
328 /// LEMON_ASSERT(false, msg);
330 # define LEMON_FIXME(msg) \
331 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \
332 "FIXME: " msg, static_cast<const char*>(0)))
336 # ifndef LEMON_ASSERT_HANDLER
337 # define LEMON_ASSERT(exp, msg) (static_cast<void>(0))
338 # define LEMON_FIXME(msg) (static_cast<void>(0))
340 # define LEMON_ASSERT(exp, msg) \
341 (static_cast<void> (!!(exp) ? 0 : ( \
342 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
343 LEMON_FUNCTION_NAME, \
345 # define LEMON_FIXME(msg) \
346 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \
347 "FIXME: " msg, static_cast<const char*>(0)))