libstdc++
system_error
Go to the documentation of this file.
00001 // <system_error> -*- C++ -*-
00002 
00003 // Copyright (C) 2007-2014 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file include/system_error
00026  *  This is a Standard C++ Library header.
00027  */
00028 
00029 #ifndef _GLIBCXX_SYSTEM_ERROR
00030 #define _GLIBCXX_SYSTEM_ERROR 1
00031 
00032 #pragma GCC system_header
00033 
00034 #if __cplusplus < 201103L
00035 # include <bits/c++0x_warning.h>
00036 #else
00037 
00038 #include <bits/c++config.h>
00039 #include <bits/error_constants.h>
00040 #include <iosfwd>
00041 #include <stdexcept>
00042 
00043 namespace std _GLIBCXX_VISIBILITY(default)
00044 {
00045 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00046 
00047   class error_code;
00048   class error_condition;
00049   class error_category;
00050   class system_error;
00051 
00052   /// is_error_code_enum
00053   template<typename _Tp>
00054     struct is_error_code_enum : public false_type { };
00055 
00056   /// is_error_condition_enum
00057   template<typename _Tp>
00058     struct is_error_condition_enum : public false_type { };
00059 
00060   template<> 
00061     struct is_error_condition_enum<errc>
00062     : public true_type { };
00063 
00064 
00065   /// error_category
00066   class error_category
00067   {
00068   public:
00069 #ifdef _GLIBCXX_COMPATIBILITY_CXX0X
00070     error_category() noexcept;
00071 #else
00072     constexpr error_category() noexcept = default;
00073 #endif
00074 
00075     virtual ~error_category();
00076 
00077     error_category(const error_category&) = delete;
00078     error_category& operator=(const error_category&) = delete;
00079 
00080     virtual const char* 
00081     name() const noexcept = 0;
00082 
00083     virtual string 
00084     message(int) const = 0;
00085 
00086     virtual error_condition
00087     default_error_condition(int __i) const noexcept;
00088 
00089     virtual bool 
00090     equivalent(int __i, const error_condition& __cond) const noexcept;
00091 
00092     virtual bool 
00093     equivalent(const error_code& __code, int __i) const noexcept;
00094 
00095     bool 
00096     operator<(const error_category& __other) const noexcept
00097     { return less<const error_category*>()(this, &__other); }
00098 
00099     bool 
00100     operator==(const error_category& __other) const noexcept
00101     { return this == &__other; }
00102 
00103     bool 
00104     operator!=(const error_category& __other) const noexcept
00105     { return this != &__other; }
00106   };
00107 
00108   // DR 890.
00109   _GLIBCXX_CONST const error_category& system_category() noexcept;
00110   _GLIBCXX_CONST const error_category& generic_category() noexcept;
00111 
00112   error_code make_error_code(errc) noexcept;
00113 
00114   template<typename _Tp>
00115     struct hash;
00116 
00117   /// error_code
00118   // Implementation-specific error identification
00119   struct error_code
00120   {
00121     error_code() noexcept
00122     : _M_value(0), _M_cat(&system_category()) { }
00123 
00124     error_code(int __v, const error_category& __cat) noexcept
00125     : _M_value(__v), _M_cat(&__cat) { }
00126 
00127     template<typename _ErrorCodeEnum, typename = typename
00128          enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
00129       error_code(_ErrorCodeEnum __e) noexcept
00130       { *this = make_error_code(__e); }
00131 
00132     void 
00133     assign(int __v, const error_category& __cat) noexcept
00134     {
00135       _M_value = __v;
00136       _M_cat = &__cat; 
00137     }
00138 
00139     void 
00140     clear() noexcept
00141     { assign(0, system_category()); }
00142 
00143     // DR 804.
00144     template<typename _ErrorCodeEnum>
00145       typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
00146              error_code&>::type
00147       operator=(_ErrorCodeEnum __e) noexcept
00148       { return *this = make_error_code(__e); }
00149 
00150     int
00151     value() const noexcept { return _M_value; }
00152       
00153     const error_category&  
00154     category() const noexcept { return *_M_cat; }
00155 
00156     error_condition 
00157     default_error_condition() const noexcept;
00158 
00159     string 
00160     message() const
00161     { return category().message(value()); }
00162 
00163     explicit operator bool() const noexcept
00164     { return _M_value != 0 ? true : false; }
00165 
00166     // DR 804.
00167   private:
00168     friend class hash<error_code>;
00169 
00170     int                 _M_value;
00171     const error_category*   _M_cat;
00172   };
00173 
00174   // 19.4.2.6 non-member functions
00175   inline error_code
00176   make_error_code(errc __e) noexcept
00177   { return error_code(static_cast<int>(__e), generic_category()); }
00178 
00179   inline bool
00180   operator<(const error_code& __lhs, const error_code& __rhs) noexcept
00181   { 
00182     return (__lhs.category() < __rhs.category()
00183         || (__lhs.category() == __rhs.category()
00184         && __lhs.value() < __rhs.value()));
00185   }
00186 
00187   template<typename _CharT, typename _Traits>
00188     basic_ostream<_CharT, _Traits>&
00189     operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
00190     { return (__os << __e.category().name() << ':' << __e.value()); }
00191 
00192   error_condition make_error_condition(errc) noexcept;
00193 
00194   /// error_condition
00195   // Portable error identification
00196   struct error_condition 
00197   {
00198     error_condition() noexcept
00199     : _M_value(0), _M_cat(&generic_category()) { }
00200 
00201     error_condition(int __v, const error_category& __cat) noexcept
00202     : _M_value(__v), _M_cat(&__cat) { }
00203 
00204     template<typename _ErrorConditionEnum, typename = typename
00205      enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
00206       error_condition(_ErrorConditionEnum __e) noexcept
00207       { *this = make_error_condition(__e); }
00208 
00209     void
00210     assign(int __v, const error_category& __cat) noexcept
00211     {
00212       _M_value = __v;
00213       _M_cat = &__cat;
00214     }
00215 
00216     // DR 804.
00217     template<typename _ErrorConditionEnum>
00218       typename enable_if<is_error_condition_enum
00219              <_ErrorConditionEnum>::value, error_condition&>::type
00220       operator=(_ErrorConditionEnum __e) noexcept
00221       { return *this = make_error_condition(__e); }
00222 
00223     void 
00224     clear() noexcept
00225     { assign(0, generic_category()); }
00226 
00227     // 19.4.3.4 observers
00228     int
00229     value() const noexcept { return _M_value; }
00230 
00231     const error_category&
00232     category() const noexcept { return *_M_cat; }
00233 
00234     string 
00235     message() const
00236     { return category().message(value()); }
00237 
00238     explicit operator bool() const noexcept
00239     { return _M_value != 0 ? true : false; }
00240 
00241     // DR 804.
00242   private:
00243     int             _M_value;
00244     const error_category*   _M_cat;
00245   };
00246 
00247   // 19.4.3.6 non-member functions
00248   inline error_condition
00249   make_error_condition(errc __e) noexcept
00250   { return error_condition(static_cast<int>(__e), generic_category()); }
00251 
00252   inline bool 
00253   operator<(const error_condition& __lhs,
00254         const error_condition& __rhs) noexcept
00255   {
00256     return (__lhs.category() < __rhs.category()
00257         || (__lhs.category() == __rhs.category()
00258         && __lhs.value() < __rhs.value()));
00259   }
00260 
00261   // 19.4.4 Comparison operators
00262   inline bool
00263   operator==(const error_code& __lhs, const error_code& __rhs) noexcept
00264   { return (__lhs.category() == __rhs.category()
00265         && __lhs.value() == __rhs.value()); }
00266 
00267   inline bool
00268   operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
00269   {
00270     return (__lhs.category().equivalent(__lhs.value(), __rhs)
00271         || __rhs.category().equivalent(__lhs, __rhs.value()));
00272   }
00273 
00274   inline bool
00275   operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
00276   {
00277     return (__rhs.category().equivalent(__rhs.value(), __lhs)
00278         || __lhs.category().equivalent(__rhs, __lhs.value()));
00279   }
00280 
00281   inline bool
00282   operator==(const error_condition& __lhs,
00283          const error_condition& __rhs) noexcept
00284   {
00285     return (__lhs.category() == __rhs.category()
00286         && __lhs.value() == __rhs.value());
00287   }
00288 
00289   inline bool
00290   operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
00291   { return !(__lhs == __rhs); }
00292 
00293   inline bool
00294   operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
00295   { return !(__lhs == __rhs); }
00296 
00297   inline bool
00298   operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
00299   { return !(__lhs == __rhs); }
00300 
00301   inline bool
00302   operator!=(const error_condition& __lhs,
00303          const error_condition& __rhs) noexcept
00304   { return !(__lhs == __rhs); }
00305 
00306 
00307   /** 
00308    *  @brief Thrown to indicate error code of underlying system.
00309    *
00310    *  @ingroup exceptions
00311    */
00312   class system_error : public std::runtime_error
00313   {
00314   private:
00315     error_code  _M_code;
00316 
00317   public:
00318     system_error(error_code __ec = error_code())
00319     : runtime_error(__ec.message()), _M_code(__ec) { }
00320 
00321     system_error(error_code __ec, const string& __what)
00322     : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
00323 
00324     /*
00325      * TODO: Add const char* ctors to all exceptions.
00326      *
00327      * system_error(error_code __ec, const char* __what)
00328      * : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
00329      *
00330      * system_error(int __v, const error_category& __ecat, const char* __what)
00331      * : runtime_error(__what + (": " + __ec.message())),
00332      *   _M_code(error_code(__v, __ecat)) { }
00333      */
00334 
00335     system_error(int __v, const error_category& __ecat)
00336     : runtime_error(error_code(__v, __ecat).message()),
00337       _M_code(__v, __ecat) { }
00338 
00339     system_error(int __v, const error_category& __ecat, const string& __what)
00340     : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
00341       _M_code(__v, __ecat) { }
00342 
00343     virtual ~system_error() noexcept;
00344 
00345     const error_code& 
00346     code() const noexcept { return _M_code; }
00347   };
00348 
00349 _GLIBCXX_END_NAMESPACE_VERSION
00350 } // namespace
00351 
00352 #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
00353 
00354 #include <bits/functional_hash.h>
00355 
00356 namespace std _GLIBCXX_VISIBILITY(default)
00357 {
00358 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00359 
00360   // DR 1182.
00361   /// std::hash specialization for error_code.
00362   template<>
00363     struct hash<error_code>
00364     : public __hash_base<size_t, error_code>
00365     {
00366       size_t
00367       operator()(const error_code& __e) const noexcept
00368       {
00369     const size_t __tmp = std::_Hash_impl::hash(__e._M_value);
00370     return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp);
00371       }
00372     };
00373 
00374 _GLIBCXX_END_NAMESPACE_VERSION
00375 } // namespace
00376 
00377 #endif // _GLIBCXX_COMPATIBILITY_CXX0X
00378 
00379 #endif // C++11
00380 
00381 #endif // _GLIBCXX_SYSTEM_ERROR