// (C) Copyright 2004: Reece H. Dunn #ifndef BOOST_ERRORCHECK_HPP #define BOOST_ERRORCHECK_HPP #include #include namespace boost { namespace policy { // StoragePolicy -- holds the error value and checks for failure template< typename T = int > class error_storage { public: typedef T error_type; private: T error; public: inline bool failed() const { return( error < 0 ); } public: inline error_storage & operator=( T e ) { error = e; return( *this ); } public: inline error_storage(): error() { } inline error_storage( T e ): error( e ) { } }; // ErrorMsgPolicy -- holds a description of the origin of the error class no_errormsg_storage { public: inline const char * get_msg() const { return( "unspecified error" ); } }; class errormsg_storage { private: const char * msg; public: inline void set_msg( const char * m ) { msg = m; } inline const char * get_msg() const { return( msg ? msg : "unspecified error" ); } public: inline errormsg_storage(): msg( 0 ) { } }; class errnomsg_storage { public: inline int get_errno() const { return( errno ); } inline const char * get_msg() const { return( strerror( errno )); } }; } template < typename Storage = policy::error_storage<>, typename MsgStorage = policy::no_errormsg_storage > class errorcheck; namespace detail // adapted from http://www.research.att.com/~bs/bs_faq2.html#no-derivation { template< typename Storage, typename MsgStorage > class cannot_derive_errorcheck { friend class boost::errorcheck< Storage, MsgStorage >; private: cannot_derive_errorcheck() { } cannot_derive_errorcheck( const cannot_derive_errorcheck & ) { } }; } template< typename Storage, typename MsgStorage > class errorcheck: public Storage, public MsgStorage, public virtual detail::cannot_derive_errorcheck< Storage, MsgStorage > { public: inline errorcheck & operator=( typename Storage::error_type e ) { Storage::operator=( e ); if( failed()) throw( *this ); return( *this ); } inline errorcheck & operator=( const errorcheck & ec ) { Storage::operator=( ec ); return( *this ); } public: inline errorcheck & operator()( bool cond ) { if( !cond ) throw( *this ); return( *this ); } inline errorcheck & operator()( const char * m ) { MsgStorage::set_msg( m ); return( *this ); } private: inline errorcheck( const Storage & s, const MsgStorage & ms ): Storage( s ), MsgStorage( ms ) { } public: inline errorcheck(): Storage(), MsgStorage() { } inline errorcheck( const errorcheck & ec ): Storage( ec ), MsgStorage( ec ) { } inline errorcheck( typename Storage::error_type e ): Storage( e ), MsgStorage() { // [note]: workaround for throwing an unconstructed errorcheck object if( failed()) throw( errorcheck< Storage, MsgStorage >( *this, *this )); } }; } #endif