libstdc++
system_error
Go to the documentation of this file.
00001 // <system_error> -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008, 2009, 2010, 2011 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 #ifndef __GXX_EXPERIMENTAL_CXX0X__
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   protected:
00069     error_category() noexcept;
00070 
00071   public:
00072     virtual ~error_category() noexcept;
00073 
00074     error_category(const error_category&) = delete;
00075     error_category& operator=(const error_category&) = delete;
00076 
00077     virtual const char* 
00078     name() const noexcept = 0;
00079 
00080     virtual string 
00081     message(int) const = 0;
00082 
00083     virtual error_condition
00084     default_error_condition(int __i) const noexcept;
00085 
00086     virtual bool 
00087     equivalent(int __i, const error_condition& __cond) const noexcept;
00088 
00089     virtual bool 
00090     equivalent(const error_code& __code, int __i) const noexcept;
00091 
00092     bool 
00093     operator<(const error_category& __other) const noexcept
00094     { return less<const error_category*>()(this, &__other); }
00095 
00096     bool 
00097     operator==(const error_category& __other) const noexcept
00098     { return this == &__other; }
00099 
00100     bool 
00101     operator!=(const error_category& __other) const noexcept
00102     { return this != &__other; }
00103   };
00104 
00105   // DR 890.
00106   _GLIBCXX_CONST const error_category& system_category() noexcept;
00107   _GLIBCXX_CONST const error_category& generic_category() noexcept;
00108 
00109   error_code make_error_code(errc) noexcept;
00110 
00111   template<typename _Tp>
00112     struct hash;
00113 
00114   /// error_code
00115   // Implementation-specific error identification
00116   struct error_code
00117   {
00118     error_code() noexcept
00119     : _M_value(0), _M_cat(&system_category()) { }
00120 
00121     error_code(int __v, const error_category& __cat) noexcept
00122     : _M_value(__v), _M_cat(&__cat) { }
00123 
00124     template<typename _ErrorCodeEnum, typename = typename
00125          enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
00126       error_code(_ErrorCodeEnum __e) noexcept
00127       { *this = make_error_code(__e); }
00128 
00129     void 
00130     assign(int __v, const error_category& __cat) noexcept
00131     {
00132       _M_value = __v;
00133       _M_cat = &__cat; 
00134     }
00135 
00136     void 
00137     clear() noexcept
00138     { assign(0, system_category()); }
00139 
00140     // DR 804.
00141     template<typename _ErrorCodeEnum>
00142       typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
00143              error_code&>::type
00144       operator=(_ErrorCodeEnum __e) noexcept
00145       { return *this = make_error_code(__e); }
00146 
00147     int
00148     value() const noexcept { return _M_value; }
00149       
00150     const error_category&  
00151     category() const noexcept { return *_M_cat; }
00152 
00153     error_condition 
00154     default_error_condition() const noexcept;
00155 
00156     string 
00157     message() const
00158     { return category().message(value()); }
00159 
00160     explicit operator bool() const noexcept
00161     { return _M_value != 0 ? true : false; }
00162 
00163     // DR 804.
00164   private:
00165     friend class hash<error_code>;
00166 
00167     int                 _M_value;
00168     const error_category*   _M_cat;
00169   };
00170 
00171   // 19.4.2.6 non-member functions
00172   inline error_code
00173   make_error_code(errc __e) noexcept
00174   { return error_code(static_cast<int>(__e), generic_category()); }
00175 
00176   inline bool
00177   operator<(const error_code& __lhs, const error_code& __rhs) noexcept
00178   { 
00179     return (__lhs.category() < __rhs.category()
00180         || (__lhs.category() == __rhs.category()
00181         && __lhs.value() < __rhs.value()));
00182   }
00183 
00184   template<typename _CharT, typename _Traits>
00185     basic_ostream<_CharT, _Traits>&
00186     operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
00187     { return (__os << __e.category().name() << ':' << __e.value()); }
00188 
00189   error_condition make_error_condition(errc) noexcept;
00190 
00191   /// error_condition
00192   // Portable error identification
00193   struct error_condition 
00194   {
00195     error_condition() noexcept
00196     : _M_value(0), _M_cat(&generic_category()) { }
00197 
00198     error_condition(int __v, const error_category& __cat) noexcept
00199     : _M_value(__v), _M_cat(&__cat) { }
00200 
00201     template<typename _ErrorConditionEnum, typename = typename
00202      enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
00203       error_condition(_ErrorConditionEnum __e) noexcept
00204       { *this = make_error_condition(__e); }
00205 
00206     void
00207     assign(int __v, const error_category& __cat) noexcept
00208     {
00209       _M_value = __v;
00210       _M_cat = &__cat;
00211     }
00212 
00213     // DR 804.
00214     template<typename _ErrorConditionEnum>
00215       typename enable_if<is_error_condition_enum
00216              <_ErrorConditionEnum>::value, error_condition&>::type
00217       operator=(_ErrorConditionEnum __e) noexcept
00218       { return *this = make_error_condition(__e); }
00219 
00220     void 
00221     clear() noexcept
00222     { assign(0, generic_category()); }
00223 
00224     // 19.4.3.4 observers
00225     int
00226     value() const noexcept { return _M_value; }
00227 
00228     const error_category&
00229     category() const noexcept { return *_M_cat; }
00230 
00231     string 
00232     message() const
00233     { return category().message(value()); }
00234 
00235     explicit operator bool() const noexcept
00236     { return _M_value != 0 ? true : false; }
00237 
00238     // DR 804.
00239   private:
00240     int             _M_value;
00241     const error_category*   _M_cat;
00242   };
00243 
00244   // 19.4.3.6 non-member functions
00245   inline error_condition
00246   make_error_condition(errc __e) noexcept
00247   { return error_condition(static_cast<int>(__e), generic_category()); }
00248 
00249   inline bool 
00250   operator<(const error_condition& __lhs,
00251         const error_condition& __rhs) noexcept
00252   {
00253     return (__lhs.category() < __rhs.category()
00254         || (__lhs.category() == __rhs.category()
00255         && __lhs.value() < __rhs.value()));
00256   }
00257 
00258   // 19.4.4 Comparison operators
00259   inline bool
00260   operator==(const error_code& __lhs, const error_code& __rhs) noexcept
00261   { return (__lhs.category() == __rhs.category()
00262         && __lhs.value() == __rhs.value()); }
00263 
00264   inline bool
00265   operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
00266   {
00267     return (__lhs.category().equivalent(__lhs.value(), __rhs)
00268         || __rhs.category().equivalent(__lhs, __rhs.value()));
00269   }
00270 
00271   inline bool
00272   operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
00273   {
00274     return (__rhs.category().equivalent(__rhs.value(), __lhs)
00275         || __lhs.category().equivalent(__rhs, __lhs.value()));
00276   }
00277 
00278   inline bool
00279   operator==(const error_condition& __lhs,
00280          const error_condition& __rhs) noexcept
00281   {
00282     return (__lhs.category() == __rhs.category()
00283         && __lhs.value() == __rhs.value());
00284   }
00285 
00286   inline bool
00287   operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
00288   { return !(__lhs == __rhs); }
00289 
00290   inline bool
00291   operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
00292   { return !(__lhs == __rhs); }
00293 
00294   inline bool
00295   operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
00296   { return !(__lhs == __rhs); }
00297 
00298   inline bool
00299   operator!=(const error_condition& __lhs,
00300          const error_condition& __rhs) noexcept
00301   { return !(__lhs == __rhs); }
00302 
00303 
00304   /** 
00305    *  @brief Thrown to indicate error code of underlying system.
00306    *
00307    *  @ingroup exceptions
00308    */
00309   class system_error : public std::runtime_error
00310   {
00311   private:
00312     error_code  _M_code;
00313 
00314   public:
00315     system_error(error_code __ec = error_code())
00316     : runtime_error(__ec.message()), _M_code(__ec) { }
00317 
00318     system_error(error_code __ec, const string& __what)
00319     : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
00320 
00321     /*
00322      * TODO: Add const char* ctors to all exceptions.
00323      *
00324      * system_error(error_code __ec, const char* __what)
00325      * : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
00326      *
00327      * system_error(int __v, const error_category& __ecat, const char* __what)
00328      * : runtime_error(__what + (": " + __ec.message())),
00329      *   _M_code(error_code(__v, __ecat)) { }
00330      */
00331 
00332     system_error(int __v, const error_category& __ecat)
00333     : runtime_error(error_code(__v, __ecat).message()),
00334       _M_code(__v, __ecat) { }
00335 
00336     system_error(int __v, const error_category& __ecat, const string& __what)
00337     : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
00338       _M_code(__v, __ecat) { }
00339 
00340     virtual ~system_error() noexcept;
00341 
00342     const error_code& 
00343     code() const noexcept { return _M_code; }
00344   };
00345 
00346 _GLIBCXX_END_NAMESPACE_VERSION
00347 } // namespace
00348 
00349 #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
00350 
00351 #include <bits/functional_hash.h>
00352 
00353 namespace std _GLIBCXX_VISIBILITY(default)
00354 {
00355 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00356 
00357   // DR 1182.
00358   /// std::hash specialization for error_code.
00359   template<>
00360     struct hash<error_code>
00361     : public __hash_base<size_t, error_code>
00362     {
00363       size_t
00364       operator()(const error_code& __e) const noexcept
00365       {
00366     const size_t __tmp = std::_Hash_impl::hash(__e._M_value);
00367     return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp);
00368       }
00369     };
00370 
00371 _GLIBCXX_END_NAMESPACE_VERSION
00372 } // namespace
00373 
00374 #endif // _GLIBCXX_COMPATIBILITY_CXX0X
00375 
00376 #endif // __GXX_EXPERIMENTAL_CXX0X__
00377 
00378 #endif // _GLIBCXX_SYSTEM_ERROR