COIN-OR::LEMON - Graph Library

Changeset 108:889d0c289d19 in lemon-1.2 for lemon/error.h


Ignore:
Timestamp:
03/25/08 16:36:44 (12 years ago)
Author:
Balazs Dezso <deba@…>
Branch:
default
Children:
109:abddaa08b507, 112:d2ee5e7f00ef
Phase:
public
Message:

Reworking assertions and moving to distinict file

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lemon/error.h

    r66 r108  
    9494  };
    9595
    96   /// Exception-safe convenient "error message" class.
     96  /// Exception-safe convenient error message builder class.
    9797
    9898  /// Helper class which provides a convenient ostream-like (operator <<
     
    414414  };
    415415
    416 
    417   ///\e
    418   class AssertionFailedError : public LogicError {
    419   protected:
    420     const char *assertion;
    421     const char *file;
    422     int line;
    423     const char *function;
    424     const char *message;
    425 
    426     mutable ExceptionMember<std::string> _message_holder;
    427   public:
    428     ///\e
    429     AssertionFailedError(const char *_file, int _line, const char *func,
    430                          const char *msg, const char *_assertion = 0) :
    431       assertion(_assertion), file(_file), line(_line), function(func),
    432       message(msg) {}
    433 
    434     ///\e
    435     const char* get_assertion() const { return assertion; }
    436     ///\e
    437     const char* get_message() const { return message; }
    438     ///\e
    439     const char* get_file() const { return file; }
    440     ///\e
    441     const char* get_function() const { return function; }
    442     ///\e
    443     int get_line() const { return line; }
    444 
    445 
    446     virtual const char* what() const throw() {
    447       try {
    448         std::ostringstream ostr;
    449         ostr << file << ":" << line << ": ";
    450         if( function )
    451           ostr << function << ": ";
    452         ostr << message;
    453         if( assertion )
    454            ostr << " (assertion '" << assertion << "' failed)";
    455         _message_holder.set(ostr.str());
    456         return ostr.str().c_str();
    457       }
    458       catch(...) {}
    459       if( _message_holder.valid() ) return _message_holder.get().c_str();
    460       return "lemon::AssertionFailedError";
    461     }
    462    virtual ~AssertionFailedError() throw() {}
    463   };
    464 
    465 
    466   /****************  Macros  ****************/
    467 
    468 
    469   template <typename Exception>
    470   inline void assert_fail(const char *file, int line,
    471                           const char *func,
    472                           Exception exception,
    473                           const char *assertion = 0,
    474                           bool do_abort=true)
    475   {
    476     using namespace std;
    477     cerr << file << ":" << line << ": ";
    478     if (func)
    479       cerr << func << ": ";
    480     cerr << exception.what();
    481     if (assertion)
    482       cerr << " (assertion '" << assertion << "' failed)";
    483     cerr << endl;
    484     if (do_abort)
    485       abort();
    486   }
    487 
    488   template <>
    489   inline void assert_fail<const char *>(const char *file, int line,
    490                                         const char *func,
    491                                         const char *message,
    492                                         const char *assertion,
    493                                         bool do_abort)
    494   {
    495     using namespace std;
    496     cerr << file << ":" << line << ": ";
    497     if (func)
    498       cerr << func << ": ";
    499     cerr << message;
    500     if (assertion)
    501       cerr << " (assertion '" << assertion << "' failed)";
    502     cerr << endl;
    503     if (do_abort)
    504       abort();
    505   }
    506 
    507   template <>
    508   inline void assert_fail<std::string>(const char *file, int line,
    509                                        const char *func,
    510                                        std::string message,
    511                                        const char *assertion,
    512                                        bool do_abort)
    513   {
    514     assert_fail(file, line, func, message.c_str(), assertion, do_abort);
    515   }
    516 
    517   template <typename Exception>
    518   inline void assert_fail_failure(const char *file, int line, const char *func,
    519                            Exception exception,
    520                            const char *assertion = 0,
    521                            bool = true)
    522   {
    523     throw AssertionFailedError(file, line, func, exception.what(), assertion);
    524   }
    525 
    526   template <>
    527   inline void assert_fail_failure<const char *>(const char *file, int line,
    528                                                 const char *func,
    529                                                 const char *message,
    530                                                 const char *assertion,
    531                                                 bool)
    532   {
    533     throw AssertionFailedError(file, line, func, message, assertion);
    534   }
    535 
    536   template <>
    537   inline void assert_fail_failure<std::string>(const char *file, int line,
    538                                                const char *func,
    539                                                std::string message,
    540                                                const char *assertion,
    541                                                bool)
    542   {
    543     assert_fail_failure(file, line, func, message.c_str(), assertion, true);
    544   }
    545 
    546   template <typename Exception>
    547   inline void assert_fail_exception(const char *file, int line, const char *func,
    548                              Exception exception,
    549                              const char *assertion = 0, bool = true)
    550   {
    551     throw exception;
    552   }
    553 
    554   template <>
    555   inline void assert_fail_exception<const char *>(const char *file, int line,
    556                                            const char *func,
    557                                            const char *message,
    558                                            const char *assertion,
    559                                            bool)
    560   {
    561     throw AssertionFailedError(file, line, func, message, assertion);
    562   }
    563 
    564   template <>
    565   inline void assert_fail_exception<std::string>(const char *file, int line,
    566                                                  const char *func,
    567                                                  std::string message,
    568                                                  const char *assertion,
    569                                                  bool)
    570   {
    571     assert_fail_exception(file, line, func, message.c_str(), assertion, true);
    572   }
    573 
    574 /// @}
     416  /// @}
    575417
    576418}
     419
    577420#endif // LEMON_ERROR_H
    578 
    579 #undef LEMON_ASSERT
    580 #undef LEMON_FIXME
    581 
    582 #ifdef LEMON_ENABLE_ASSERTS
    583 #  define LEMON_ASSERT_ABORT
    584 #endif
    585 
    586 #ifndef LEMON_ASSERT_DO_ABORT
    587 #  define LEMON_ASSERT_DO_ABORT 1
    588 #endif
    589 
    590 #ifndef LEMON_ASSERT_HANDLER
    591 #  if defined LEMON_ASSERT_EXCEPTION
    592 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
    593 #  elif defined LEMON_ASSERT_FAILURE
    594 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
    595 #  elif defined LEMON_ASSERT_ABORT
    596 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
    597 #  else
    598 #    define LEMON_DISABLE_ASSERTS
    599 #  endif
    600 #endif
    601 
    602 #ifdef DOXYGEN
    603 
    604 /// \brief Macro for assertions with customizable message
    605 ///
    606 /// Macro for assertions with customizable message.
    607 ///
    608 /// The assertions are disabled in the default behaviour. You can
    609 /// enable the assertions with the
    610 /// \code
    611 /// #define LEMON_ENABLE_ASSERTS
    612 /// \endcode
    613 /// Then an assert
    614 /// provides a log on the standard error about the assertion and aborts
    615 /// the program if LEMON_ASSERT_DO_ABORT is also defined (otherwise the
    616 /// program keeps on running).
    617 /// By defining LEMON_ASSERT_FAILURE or
    618 /// LEMON_ASSERT_EXCEPTION, you can set other behaviour to the
    619 /// assertions. In case LEMON_ASSERT_FAILURE is given, LEMON_ASSERT
    620 /// will always throw an \c AssertionFailedError exception with
    621 /// the \c msg error message. By using
    622 /// LEMON_ASSERT_EXCEPTION, one can define an arbitrary exception to be thrown.
    623 ///
    624 /// The LEMON_ASSERT macro should be called with the \c exp parameter
    625 /// which should be an expression convertible to bool. If the given
    626 /// parameter is false the assertion is raised and one of the assertion
    627 /// behaviour will be activated. The \c msg should be either a const
    628 /// char* message or an exception. When the \c msg is an exception the
    629 /// \ref lemon::Exception::what() "what()" function is called to retrieve and
    630 /// display the error message.
    631 ///
    632 /// \todo We should provide some way to reset to the default behaviour,
    633 /// shouldn't we?
    634 ///
    635 /// \todo This whole 'assert' business should be placed in a separate
    636 /// include file. The boost assert is not guarded by header sentries
    637 /// which may help to change the behaviour of the assertions in
    638 /// the files.
    639 ///
    640 /// \todo __PRETTY_FUNCTION__ should be replaced by something
    641 /// compiler-independent, like BOOST_CURRENT_FUNCTION
    642 
    643 #  define LEMON_ASSERT(exp, msg)                 \
    644      (static_cast<void> (!!(exp) ? 0 : (         \
    645        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
    646                             __PRETTY_FUNCTION__, \
    647                             msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))
    648 
    649 #else
    650 #  if defined LEMON_DISABLE_ASSERTS
    651 
    652 #    define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
    653 
    654 #  else
    655 #    define LEMON_ASSERT(exp, msg)                 \
    656        (static_cast<void> (!!(exp) ? 0 : (         \
    657          LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
    658                               __PRETTY_FUNCTION__, \
    659                               msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))
    660 #  endif
    661 #endif
    662 
    663 /**
    664  * \brief Macro for mark not yet implemented features.
    665  *
    666  * \todo Is this the right place for this? It should be used only in
    667  * modules under development.
    668  *
    669  * \todo __PRETTY_FUNCTION__ should be replaced by something
    670  * compiler-independent, like BOOST_CURRENT_FUNCTION
    671  */
    672 
    673 #define LEMON_FIXME(msg) \
    674     (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
    675                           "FIXME: " msg))
Note: See TracChangeset for help on using the changeset viewer.