Bug fix.
Default assign operator should be
overrided by that calls the template
assign operator.
     2  * lemon/error.h - Part of LEMON, a generic C++ optimization library
 
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi
 
     5  * Kutatocsoport (Egervary Research Group on Combinatorial Optimization,
 
     8  * Permission to use, modify and distribute this software is granted
 
     9  * provided that this copyright notice appears in all copies. For
 
    10  * precise terms see the accompanying LICENSE file.
 
    12  * This software is provided "AS IS" with no warranty of any kind,
 
    13  * express or implied, and with no claim as to its suitability for any
 
    21 //! \ingroup exceptions
 
    23 //! \brief Basic exception classes and error handling.
 
    34   /// \addtogroup exceptions
 
    37   /// \brief Exception safe wrapper class.
 
    39   /// Exception safe wrapper class to implement the members of exceptions.
 
    40   template <typename _Type>
 
    41   class ExceptionMember {
 
    45     ExceptionMember() throw () {
 
    47 	ptr.reset(new Type());
 
    51     ExceptionMember(const Type& type) throw () {
 
    53 	ptr.reset(new Type());
 
    54 	if (ptr.get() == 0) return;
 
    59     ExceptionMember(const ExceptionMember& copy) throw() {
 
    61 	if (!copy.valid()) return;
 
    62 	ptr.reset(new Type());
 
    63 	if (ptr.get() == 0) return;
 
    68     ExceptionMember& operator=(const ExceptionMember& copy) {
 
    69       if (ptr.get() == 0) return;
 
    71 	if (!copy.valid()) return;
 
    76     void set(const Type& type) {
 
    77       if (ptr.get() == 0) return;
 
    83     const Type& get() const {
 
    88       return ptr.get() != 0;
 
    92     std::auto_ptr<_Type> ptr;
 
    95   /// Exception-safe convenient "error message" class.
 
    97   /// Helper class which provides a convenient ostream-like (operator <<
 
    98   /// based) interface to create a string message. Mostly useful in
 
    99   /// exception classes (therefore the name).
 
   104     ///\todo The good solution is boost::shared_ptr...
 
   107     std::auto_ptr<std::ostringstream> buf;
 
   110     bool init() throw() {
 
   112 	buf.reset(new std::ostringstream);
 
   123     ErrorMessage() throw() { init(); }
 
   125     ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
 
   128     ErrorMessage(const char *message) throw() {
 
   134     ErrorMessage(const std::string &message) throw() {
 
   140     template <typename T>
 
   141     ErrorMessage& operator<<(const T &t) throw() {
 
   142       if( ! buf.get() ) return *this;
 
   154     const char* message() throw() {
 
   155       if( ! buf.get() ) return 0;
 
   159 	mes = buf->str().c_str();
 
   168    * \brief Generic exception class.
 
   170    * Base class for exceptions used in LEMON.
 
   172   class Exception : public std::exception {
 
   177     virtual ~Exception() throw() {}
 
   180     virtual const char* exceptionName() const {
 
   181       return "lemon::Exception";
 
   185     virtual const char* what() const throw() {
 
   186       return exceptionName();
 
   191    * \brief One of the two main subclasses of \ref Exception.
 
   193    * Logic errors represent problems in the internal logic of a program;
 
   194    * in theory, these are preventable, and even detectable before the
 
   195    * program runs (e.g., violations of class invariants).
 
   197    * A typical example for this is \ref UninitializedParameter.
 
   199   class LogicError : public Exception {
 
   201     virtual const char* exceptionName() const {
 
   202       return "lemon::LogicError";
 
   207    * \brief \ref Exception for uninitialized parameters.
 
   209    * This error represents problems in the initialization
 
   210    * of the parameters of the algorithms.
 
   212   class UninitializedParameter : public LogicError {
 
   214     virtual const char* exceptionName() const {
 
   215       return "lemon::UninitializedParameter";
 
   221    * \brief One of the two main subclasses of \ref Exception.
 
   223    * Runtime errors represent problems outside the scope of a program;
 
   224    * they cannot be easily predicted and can generally only be caught as
 
   225    * the program executes.
 
   227   class RuntimeError : public Exception {
 
   229     virtual const char* exceptionName() const {
 
   230       return "lemon::RuntimeError";
 
   235   class RangeError : public RuntimeError {
 
   237     virtual const char* exceptionName() const {
 
   238       return "lemon::RangeError";
 
   243   class IOError : public RuntimeError {
 
   245     virtual const char* exceptionName() const {
 
   246       return "lemon::IOError";
 
   251   class DataFormatError : public IOError {
 
   253     ExceptionMember<std::string> _message;
 
   254     ExceptionMember<std::string> _file;
 
   257     mutable ExceptionMember<std::string> _message_holder;
 
   260     DataFormatError(const DataFormatError &dfe) : 
 
   261       IOError(dfe), _message(dfe._message), _file(dfe._file),
 
   265     explicit DataFormatError(const char *the_message)
 
   266       : _message(the_message), _line(0) {}
 
   269     DataFormatError(const std::string &file_name, int line_num,
 
   270 		    const char *the_message)
 
   271       : _message(the_message), _line(line_num) { file(file_name); }
 
   274     void line(int line) { _line = line; }
 
   276     void message(const std::string& message) { _message.set(message); }
 
   278     void file(const std::string &file) { _file.set(file); }
 
   281     int line() const { return _line; }
 
   283     const char* message() const { 
 
   284       if (_message.valid() && !_message.get().empty()) {
 
   285 	return _message.get().c_str();
 
   291     /// \brief Returns the filename.
 
   293     /// Returns \e null if the filename was not specified.
 
   294     const char* file() const {
 
   295       if (_file.valid() && !_file.get().empty()) {
 
   296 	return _file.get().c_str();
 
   303     virtual const char* what() const throw() {
 
   305 	std::ostringstream ostr;
 
   306 	ostr << exceptionName() << ": ";
 
   307 	if (message()) ostr << message();
 
   308 	if( file() || line() != 0 ) {
 
   310 	  if( file() ) ostr << "in file '" << file() << "'";
 
   311 	  if( file() && line() != 0 ) ostr << " ";
 
   312 	  if( line() != 0 ) ostr << "at line " << line();
 
   315 	_message_holder.set(ostr.str());
 
   318       if( _message_holder.valid()) return _message_holder.get().c_str();
 
   319       return exceptionName();
 
   322     virtual const char* exceptionName() const {
 
   323       return "lemon::DataFormatError";
 
   326     virtual ~DataFormatError() throw() {}
 
   329   class IOParameterError : public LogicError {
 
   331     ExceptionMember<std::string> _message;
 
   332     ExceptionMember<std::string> _file;
 
   334     mutable ExceptionMember<std::string> _message_holder;
 
   337     IOParameterError(const IOParameterError &ile) : 
 
   338       LogicError(ile), _message(ile._message), _file(ile._file) {}
 
   341     explicit IOParameterError(const char *the_message)
 
   342       : _message(the_message) {}
 
   345     IOParameterError(const char *file_name, const char *the_message)
 
   346       : _message(the_message), _file(file_name) {}
 
   349     void message(const std::string& message) { _message.set(message); }
 
   351     void file(const std::string &file) { _file.set(file); }
 
   354     const char* message() const { 
 
   355       if (_message.valid()) {
 
   356 	return _message.get().c_str();
 
   362     /// \brief Returns the filename.
 
   364     /// Returns \e null if the filename was not specified.
 
   365     const char* file() const {
 
   367 	return _file.get().c_str();
 
   374     virtual const char* what() const throw() {
 
   376 	std::ostringstream ostr;
 
   377 	if (message()) ostr << message();
 
   378 	if (file()) ostr << "(when reading file '" << file() << "')";
 
   379 	_message_holder.set(ostr.str());
 
   382       if( _message_holder.valid() ) return _message_holder.get().c_str();
 
   383       return exceptionName();
 
   386     virtual const char* exceptionName() const {
 
   387       return "lemon::IOParameterError";
 
   390     virtual ~IOParameterError() throw() {}
 
   395   class AssertionFailedError : public LogicError {
 
   397     const char *assertion;
 
   400     const char *function;
 
   403     mutable ExceptionMember<std::string> _message_holder;
 
   406     AssertionFailedError(const char *_file, int _line, const char *func,
 
   407 			 const char *msg, const char *_assertion = 0) :
 
   408       assertion(_assertion), file(_file), line(_line), function(func),
 
   412     const char* get_assertion() const { return assertion; }
 
   414     const char* get_message() const { return message; }
 
   416     const char* get_file() const { return file; }
 
   418     const char* get_function() const { return function; }
 
   420     int get_line() const { return line; }
 
   423     virtual const char* what() const throw() {
 
   425 	std::ostringstream ostr;
 
   426 	ostr << file << ":" << line << ": ";
 
   428 	  ostr << function << ": ";
 
   431 	   ostr << " (assertion '" << assertion << "' failed)";
 
   432 	_message_holder.set(ostr.str());
 
   433 	return ostr.str().c_str();
 
   436       if( _message_holder.valid() ) return _message_holder.get().c_str();
 
   437       return exceptionName();
 
   440     virtual const char* exceptionName() const {
 
   441       return "lemon::AssertionFailedError";
 
   444     virtual ~AssertionFailedError() throw() {}
 
   448   /****************  Macros  ****************/
 
   452   void assert_fail(const char *file, int line, const char *func,
 
   453 		   const char *message, const char *assertion = 0,
 
   457     cerr << file << ":" << line << ": ";
 
   459       cerr << func << ": ";
 
   462       cerr << " (assertion '" << assertion << "' failed)";
 
   469   void assert_fail_throw(const char *file, int line, const char *func,
 
   470 		   const char *message, const char *assertion = 0,
 
   473     throw AssertionFailedError(file, line, func, message, assertion);
 
   479 #endif // LEMON_ERROR_H
 
   484 #ifndef LEMON_ASSERT_ABORT
 
   485 #  define LEMON_ASSERT_ABORT 1
 
   488 #ifndef LEMON_ASSERT_HANDLER
 
   489 #  ifdef LEMON_ASSERT_EXCEPTION
 
   490 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
 
   492 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
 
   496 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
 
   498 #  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
 
   503  * \brief Macro for assertions with customizable message
 
   505  * Macro for assertions with customizable message.
 
   507  * The behaviour can be customized with LEMON_ASSERT_HANDLER,
 
   508  * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
 
   509  * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
 
   511  * \todo We should provide some way to reset to the default behaviour,
 
   514  * \todo This whole 'assert' business should be placed in a separate
 
   517  * \todo __PRETTY_FUNCTION__ should be replaced by something
 
   518  * compiler-independent, like BOOST_CURRENT_FUNCTION
 
   521 #  define LEMON_ASSERT(exp, msg)                 \
 
   522      (static_cast<void> (!!(exp) ? 0 : (         \
 
   523        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
 
   524                             __PRETTY_FUNCTION__, \
 
   525 			    (msg), #exp, LEMON_ASSERT_ABORT), 0)))
 
   527 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
 
   530  * \brief Macro for mark not yet implemented features.
 
   532  * \todo Is this the right place for this? It should be used only in
 
   533  * modules under development.
 
   535  * \todo __PRETTY_FUNCTION__ should be replaced by something
 
   536  * compiler-independent, like BOOST_CURRENT_FUNCTION
 
   539 # define LEMON_FIXME(msg) \
 
   540     (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \