libstdc++
system_error
Go to the documentation of this file.
00001 // <system_error> -*- C++ -*-
00002 
00003 // Copyright (C) 2007-2017 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 system_error;
00050 
00051   /// is_error_code_enum
00052   template<typename _Tp>
00053     struct is_error_code_enum : public false_type { };
00054 
00055   /// is_error_condition_enum
00056   template<typename _Tp>
00057     struct is_error_condition_enum : public false_type { };
00058 
00059   template<>
00060     struct is_error_condition_enum<errc>
00061     : public true_type { };
00062 
00063 #if __cplusplus > 201402L
00064   template <typename _Tp>
00065     inline constexpr bool is_error_code_enum_v =
00066       is_error_code_enum<_Tp>::value;
00067   template <typename _Tp>
00068     inline constexpr bool is_error_condition_enum_v =
00069       is_error_condition_enum<_Tp>::value;
00070 #endif // C++17
00071   inline namespace _V2 {
00072 
00073   /// error_category
00074   class error_category
00075   {
00076   public:
00077     constexpr error_category() noexcept = default;
00078 
00079     virtual ~error_category();
00080 
00081     error_category(const error_category&) = delete;
00082     error_category& operator=(const error_category&) = delete;
00083 
00084     virtual const char*
00085     name() const noexcept = 0;
00086 
00087     // We need two different virtual functions here, one returning a
00088     // COW string and one returning an SSO string. Their positions in the
00089     // vtable must be consistent for dynamic dispatch to work, but which one
00090     // the name "message()" finds depends on which ABI the caller is using.
00091 #if _GLIBCXX_USE_CXX11_ABI
00092   private:
00093     _GLIBCXX_DEFAULT_ABI_TAG
00094     virtual __cow_string
00095     _M_message(int) const;
00096 
00097   public:
00098     _GLIBCXX_DEFAULT_ABI_TAG
00099     virtual string
00100     message(int) const = 0;
00101 #else
00102     virtual string
00103     message(int) const = 0;
00104 
00105   private:
00106     virtual __sso_string
00107     _M_message(int) const;
00108 #endif
00109 
00110   public:
00111     virtual error_condition
00112     default_error_condition(int __i) const noexcept;
00113 
00114     virtual bool
00115     equivalent(int __i, const error_condition& __cond) const noexcept;
00116 
00117     virtual bool
00118     equivalent(const error_code& __code, int __i) const noexcept;
00119 
00120     bool
00121     operator<(const error_category& __other) const noexcept
00122     { return less<const error_category*>()(this, &__other); }
00123 
00124     bool
00125     operator==(const error_category& __other) const noexcept
00126     { return this == &__other; }
00127 
00128     bool
00129     operator!=(const error_category& __other) const noexcept
00130     { return this != &__other; }
00131   };
00132 
00133   // DR 890.
00134   _GLIBCXX_CONST const error_category& system_category() noexcept;
00135   _GLIBCXX_CONST const error_category& generic_category() noexcept;
00136 
00137   } // end inline namespace
00138 
00139   error_code make_error_code(errc) noexcept;
00140 
00141   template<typename _Tp>
00142     struct hash;
00143 
00144   /// error_code
00145   // Implementation-specific error identification
00146   struct error_code
00147   {
00148     error_code() noexcept
00149     : _M_value(0), _M_cat(&system_category()) { }
00150 
00151     error_code(int __v, const error_category& __cat) noexcept
00152     : _M_value(__v), _M_cat(&__cat) { }
00153 
00154     template<typename _ErrorCodeEnum, typename = typename
00155              enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
00156       error_code(_ErrorCodeEnum __e) noexcept
00157       { *this = make_error_code(__e); }
00158 
00159     void
00160     assign(int __v, const error_category& __cat) noexcept
00161     {
00162       _M_value = __v;
00163       _M_cat = &__cat;
00164     }
00165 
00166     void
00167     clear() noexcept
00168     { assign(0, system_category()); }
00169 
00170     // DR 804.
00171     template<typename _ErrorCodeEnum>
00172       typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
00173                          error_code&>::type
00174       operator=(_ErrorCodeEnum __e) noexcept
00175       { return *this = make_error_code(__e); }
00176 
00177     int
00178     value() const noexcept { return _M_value; }
00179 
00180     const error_category&
00181     category() const noexcept { return *_M_cat; }
00182 
00183     error_condition
00184     default_error_condition() const noexcept;
00185 
00186     _GLIBCXX_DEFAULT_ABI_TAG
00187     string
00188     message() const
00189     { return category().message(value()); }
00190 
00191     explicit operator bool() const noexcept
00192     { return _M_value != 0; }
00193 
00194     // DR 804.
00195   private:
00196     friend class hash<error_code>;
00197 
00198     int                         _M_value;
00199     const error_category*       _M_cat;
00200   };
00201 
00202   // 19.4.2.6 non-member functions
00203   inline error_code
00204   make_error_code(errc __e) noexcept
00205   { return error_code(static_cast<int>(__e), generic_category()); }
00206 
00207   inline bool
00208   operator<(const error_code& __lhs, const error_code& __rhs) noexcept
00209   {
00210     return (__lhs.category() < __rhs.category()
00211             || (__lhs.category() == __rhs.category()
00212                 && __lhs.value() < __rhs.value()));
00213   }
00214 
00215   template<typename _CharT, typename _Traits>
00216     basic_ostream<_CharT, _Traits>&
00217     operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
00218     { return (__os << __e.category().name() << ':' << __e.value()); }
00219 
00220   error_condition make_error_condition(errc) noexcept;
00221 
00222   /// error_condition
00223   // Portable error identification
00224   struct error_condition
00225   {
00226     error_condition() noexcept
00227     : _M_value(0), _M_cat(&generic_category()) { }
00228 
00229     error_condition(int __v, const error_category& __cat) noexcept
00230     : _M_value(__v), _M_cat(&__cat) { }
00231 
00232     template<typename _ErrorConditionEnum, typename = typename
00233          enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
00234       error_condition(_ErrorConditionEnum __e) noexcept
00235       { *this = make_error_condition(__e); }
00236 
00237     void
00238     assign(int __v, const error_category& __cat) noexcept
00239     {
00240       _M_value = __v;
00241       _M_cat = &__cat;
00242     }
00243 
00244     // DR 804.
00245     template<typename _ErrorConditionEnum>
00246       typename enable_if<is_error_condition_enum
00247                          <_ErrorConditionEnum>::value, error_condition&>::type
00248       operator=(_ErrorConditionEnum __e) noexcept
00249       { return *this = make_error_condition(__e); }
00250 
00251     void
00252     clear() noexcept
00253     { assign(0, generic_category()); }
00254 
00255     // 19.4.3.4 observers
00256     int
00257     value() const noexcept { return _M_value; }
00258 
00259     const error_category&
00260     category() const noexcept { return *_M_cat; }
00261 
00262     _GLIBCXX_DEFAULT_ABI_TAG
00263     string
00264     message() const
00265     { return category().message(value()); }
00266 
00267     explicit operator bool() const noexcept
00268     { return _M_value != 0; }
00269 
00270     // DR 804.
00271   private:
00272     int                         _M_value;
00273     const error_category*       _M_cat;
00274   };
00275 
00276   // 19.4.3.6 non-member functions
00277   inline error_condition
00278   make_error_condition(errc __e) noexcept
00279   { return error_condition(static_cast<int>(__e), generic_category()); }
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.category() == __rhs.category()
00287                 && __lhs.value() < __rhs.value()));
00288   }
00289 
00290   // 19.4.4 Comparison operators
00291   inline bool
00292   operator==(const error_code& __lhs, const error_code& __rhs) noexcept
00293   { return (__lhs.category() == __rhs.category()
00294             && __lhs.value() == __rhs.value()); }
00295 
00296   inline bool
00297   operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
00298   {
00299     return (__lhs.category().equivalent(__lhs.value(), __rhs)
00300             || __rhs.category().equivalent(__lhs, __rhs.value()));
00301   }
00302 
00303   inline bool
00304   operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
00305   {
00306     return (__rhs.category().equivalent(__rhs.value(), __lhs)
00307             || __lhs.category().equivalent(__rhs, __lhs.value()));
00308   }
00309 
00310   inline bool
00311   operator==(const error_condition& __lhs,
00312              const error_condition& __rhs) noexcept
00313   {
00314     return (__lhs.category() == __rhs.category()
00315             && __lhs.value() == __rhs.value());
00316   }
00317 
00318   inline bool
00319   operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
00320   { return !(__lhs == __rhs); }
00321 
00322   inline bool
00323   operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
00324   { return !(__lhs == __rhs); }
00325 
00326   inline bool
00327   operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
00328   { return !(__lhs == __rhs); }
00329 
00330   inline bool
00331   operator!=(const error_condition& __lhs,
00332              const error_condition& __rhs) noexcept
00333   { return !(__lhs == __rhs); }
00334 
00335 
00336   /**
00337    *  @brief Thrown to indicate error code of underlying system.
00338    *
00339    *  @ingroup exceptions
00340    */
00341   class system_error : public std::runtime_error
00342   {
00343   private:
00344     error_code  _M_code;
00345 
00346   public:
00347     system_error(error_code __ec = error_code())
00348     : runtime_error(__ec.message()), _M_code(__ec) { }
00349 
00350     system_error(error_code __ec, const string& __what)
00351     : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
00352 
00353     system_error(error_code __ec, const char* __what)
00354     : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
00355 
00356     system_error(int __v, const error_category& __ecat, const char* __what)
00357     : system_error(error_code(__v, __ecat), __what) { }
00358 
00359     system_error(int __v, const error_category& __ecat)
00360     : runtime_error(error_code(__v, __ecat).message()),
00361       _M_code(__v, __ecat) { }
00362 
00363     system_error(int __v, const error_category& __ecat, const string& __what)
00364     : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
00365       _M_code(__v, __ecat) { }
00366 
00367     virtual ~system_error() noexcept;
00368 
00369     const error_code&
00370     code() const noexcept { return _M_code; }
00371   };
00372 
00373 _GLIBCXX_END_NAMESPACE_VERSION
00374 } // namespace
00375 
00376 #include <bits/functional_hash.h>
00377 
00378 namespace std _GLIBCXX_VISIBILITY(default)
00379 {
00380 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00381 
00382 #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
00383   // DR 1182.
00384   /// std::hash specialization for error_code.
00385   template<>
00386     struct hash<error_code>
00387     : public __hash_base<size_t, error_code>
00388     {
00389       size_t
00390       operator()(const error_code& __e) const noexcept
00391       {
00392         const size_t __tmp = std::_Hash_impl::hash(__e._M_value);
00393         return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp);
00394       }
00395     };
00396 #endif // _GLIBCXX_COMPATIBILITY_CXX0X
00397 
00398 #if __cplusplus > 201402L
00399   // DR 2686.
00400   /// std::hash specialization for error_condition.
00401   template<>
00402     struct hash<error_condition>
00403     : public __hash_base<size_t, error_condition>
00404     {
00405       size_t
00406       operator()(const error_condition& __e) const noexcept
00407       {
00408         const size_t __tmp = std::_Hash_impl::hash(__e.value());
00409         return std::_Hash_impl::__hash_combine(__e.category(), __tmp);
00410       }
00411     };
00412 #endif
00413 
00414 _GLIBCXX_END_NAMESPACE_VERSION
00415 } // namespace
00416 
00417 #endif // C++11
00418 
00419 #endif // _GLIBCXX_SYSTEM_ERROR