Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:29:19

0001 #ifndef FWCore_Utilities_Exception_h
0002 #define FWCore_Utilities_Exception_h
0003 
0004 /**
0005    This a basic exception type expected to be thrown by
0006    developer-written code.  We recommend that you use it directly.
0007    It can also be used as a base class if needed.
0008 
0009    Each Exception is identified by a category string.  This category
0010    is a short word or phrase (no spaces) that described the problem
0011    that was encountered.
0012 
0013    Information can be added to the Exception using the stream insertion
0014    operator (as one uses cout).  We recommend using it in the following
0015    manner:
0016 
0017    Example:
0018    if ((rc=func()) < 0)
0019    {
0020    throw cms::Exception("DataCorrupt") << "I died with rc = " 
0021      << rc << std::endl;
0022    }
0023 
0024    Derived types are expected to fix the category, either by
0025    1) passing a string literal to the base class constructor, or
0026    2) ensuring the developer gives a category name.
0027 
0028    Example:
0029    class InfiniteLoop : public Exception
0030    {
0031    InfiniteLoop(const std::string& msg) : Exception("InfiniteLoop",msg) { }
0032    };
0033 **/
0034 
0035 #include <list>
0036 #include <sstream>
0037 #include <string>
0038 #include <exception>
0039 #include <type_traits>
0040 
0041 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0042 #include "FWCore/Utilities/interface/Likely.h"
0043 #include "FWCore/Utilities/interface/Visibility.h"
0044 
0045 namespace cms {
0046 
0047   namespace detail {
0048     // The struct template Desired exists in order to allow us to use
0049     // SFINAE to control the instantiation of the stream insertion
0050     // member template needed to support streaming output to an object
0051     // of type cms::Exception, or a subclass of cms::Exception.
0052 
0053     template <typename T, bool b>
0054     struct Desired;
0055     template <typename T>
0056     struct Desired<T, true> {
0057       typedef T type;
0058     };
0059 
0060     // The following struct template is a metafunction which combines
0061     // two of the boost type_traits metafunctions.
0062 
0063     template <typename BASE, typename DERIVED>
0064     struct is_derived_or_same {
0065       static bool const value = std::is_base_of<BASE, DERIVED>::value || std::is_same<BASE, DERIVED>::value;
0066     };
0067 
0068   }  // namespace detail
0069 
0070   class dso_export Exception : public std::exception {
0071   public:
0072     explicit Exception(std::string const& aCategory);
0073     explicit Exception(char const* aCategory);
0074 
0075     Exception(std::string const& aCategory, std::string const& message);
0076     Exception(char const* aCategory, std::string const& message);
0077     Exception(std::string const& aCategory, char const* message);
0078     Exception(char const* aCategory, char const* message);
0079 
0080     Exception(std::string const& aCategory, std::string const& message, Exception const& another);
0081 
0082     Exception(Exception const& other);
0083     ~Exception() noexcept override;
0084 
0085     void swap(Exception& other);
0086 
0087     Exception& operator=(Exception const& other);
0088 
0089     // The signature for what() must be identical to that of std::exception::what().
0090     // This function is NOT const thread safe
0091     char const* what() const noexcept override;
0092 
0093     virtual std::string explainSelf() const;
0094 
0095     std::string const& category() const;
0096     std::string message() const;
0097     std::list<std::string> const& context() const;
0098     std::list<std::string> const& additionalInfo() const;
0099     int returnCode() const;
0100 
0101     void raise() { rethrow(); }
0102 
0103     void append(Exception const& another);
0104     void append(std::string const& more_information);
0105     void append(char const* more_information);
0106 
0107     void clearMessage();
0108     void clearContext();
0109     void clearAdditionalInfo();
0110 
0111     void addContext(std::string const& context);
0112     void addContext(char const* context);
0113 
0114     void addAdditionalInfo(std::string const& info);
0115     void addAdditionalInfo(char const* info);
0116 
0117     void setContext(std::list<std::string> const& context);
0118     void setAdditionalInfo(std::list<std::string> const& info);
0119 
0120     bool alreadyPrinted() const;
0121     void setAlreadyPrinted(bool value);
0122 
0123     virtual Exception* clone() const;
0124 
0125     // In the following templates, class E is our Exception class or
0126     // any subclass thereof. The complicated return type exists to
0127     // make sure the template can only be instantiated for such
0128     // classes.
0129     //
0130 
0131     // We have provided versions of these templates which accept, and
0132     // return, reference-to-const objects of type E. These are needed
0133     // so that the expression:
0134     //
0135     //     throw Exception("category") << "some message";
0136     //
0137     // shall compile. The technical reason is that the un-named
0138     // temporary created by the explicit call to the constructor
0139     // allows only const access, except by member functions. It seems
0140     // extremely unlikely that any Exception object will be created in
0141     // read-only memory; thus it seems unlikely that allowing the
0142     // stream operators to write into a nominally 'const' Exception
0143     // object is a real danger.
0144 
0145     template <typename E, typename T>
0146     friend typename detail::Desired<E, detail::is_derived_or_same<Exception, std::remove_reference_t<E>>::value>::type&
0147     operator<<(E&& e, T const& stuff);
0148 
0149     template <typename E>
0150     friend typename detail::Desired<E, detail::is_derived_or_same<Exception, std::remove_reference_t<E>>::value>::type&
0151     operator<<(E&& e, std::ostream& (*f)(std::ostream&));
0152 
0153     template <typename E>
0154     friend typename detail::Desired<E, detail::is_derived_or_same<Exception, std::remove_reference_t<E>>::value>::type&
0155     operator<<(E&& e, std::ios_base& (*f)(std::ios_base&));
0156 
0157     // The following two function templates should be included, to help
0158     // reduce the number of function templates instantiated. However,
0159     // GCC 3.2.3 crashes with an internal compiler error when
0160     // instantiating these functions.
0161 
0162     //     template <typename E>
0163     //     friend
0164     //     typename detail::Desired<E, (std::is_base_of<Exception,E>::value ||
0165     //               std::is_same<Exception,E>::value)>::type &
0166     //     operator<<(E& e, const char*);
0167 
0168     //    template <typename E>
0169     //    friend
0170     //    typename detail::Desired<E, (std::is_base_of<Exception,E>::value ||
0171     //                     std::is_same<Exception,E>::value)>::type &
0172     //                     operator<<(E& e, char*);
0173 
0174     // This function is deprecated and we are in the process of removing
0175     // all code that uses it from CMSSW.  It will then be deleted.
0176     std::list<std::string> history() const;
0177 
0178   private:
0179     void init(std::string const& message);
0180     virtual void rethrow();
0181     virtual int returnCode_() const;
0182 
0183     // data members
0184     std::ostringstream ost_;
0185     std::string category_;
0186     //The exception class should not be accessed across threads
0187     CMS_SA_ALLOW mutable std::string what_;
0188     std::list<std::string> context_;
0189     std::list<std::string> additionalInfo_;
0190     bool alreadyPrinted_;
0191   };
0192 
0193   inline std::ostream& operator<<(std::ostream& ost, Exception const& e) {
0194     ost << e.explainSelf();
0195     return ost;
0196   }
0197 
0198   // -------- implementation ---------
0199 
0200   template <typename E, typename T>
0201   inline typename detail::Desired<E, detail::is_derived_or_same<Exception, std::remove_reference_t<E>>::value>::type&
0202   operator<<(E&& e, T const& stuff) {
0203     e.ost_ << stuff;
0204     return e;
0205   }
0206 
0207   template <typename E>
0208   inline typename detail::Desired<E, detail::is_derived_or_same<Exception, std::remove_reference_t<E>>::value>::type&
0209   operator<<(E&& e, std::ostream& (*f)(std::ostream&)) {
0210     f(e.ost_);
0211     return e;
0212   }
0213 
0214   template <typename E>
0215   inline typename detail::Desired<E, detail::is_derived_or_same<Exception, std::remove_reference_t<E>>::value>::type&
0216   operator<<(E&& e, std::ios_base& (*f)(std::ios_base&)) {
0217     f(e.ost_);
0218     return e;
0219   }
0220 
0221   // The following four function templates should be included, to help
0222   // reduce the number of function templates instantiated. However,
0223   // GCC 3.2.3 crashes with an internal compiler error when
0224   // instantiating these functions.
0225 
0226   // template <typename E>
0227   // inline
0228   // typename detail::Desired<E, detail::is_derived_or_same<Exception,E>::value>::type &
0229   // operator<<(E& e, char const* c)
0230   // {
0231   //   e.ost_ << c;
0232   //   return e;
0233   // }
0234 
0235   // template <typename E>
0236   // inline
0237   // typename detail::Desired<E, detail::is_derived_or_same<Exception,E>::value>::type const&
0238   // operator<<(E const& e, char const* c)
0239   // {
0240   //   E& ref = const_cast<E&>(e);
0241   //   ref.ost_ << c;
0242   //   return e;
0243   // }
0244 
0245   //  template <typename E>
0246   //  inline
0247   //  typename detail::Desired<E, detail::is_derived_or_same<Exception,E>::value>::type &
0248   //  operator<<(E& e, char* c)
0249   //  {
0250   //    e.ost_ << c;
0251   //    return e;
0252   //  }
0253 
0254   //  template <typename E>
0255   //  inline
0256   //  typename detail::Desired<E, detail::is_derived_or_same<Exception,E>::value>::type const&
0257   //  operator<<(E const& e, char* c)
0258   //  {
0259   //    E& ref = const_cast<E&>(e);
0260   //    ref.ost_ << c;
0261   //    return e;
0262   //  }
0263 }  // namespace cms
0264 
0265 #endif