Home | History | Annotate | Line # | Download | only in std
      1 // <system_error> -*- C++ -*-
      2 
      3 // Copyright (C) 2007-2022 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/system_error
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #ifndef _GLIBCXX_SYSTEM_ERROR
     30 #define _GLIBCXX_SYSTEM_ERROR 1
     31 
     32 #pragma GCC system_header
     33 
     34 #if __cplusplus < 201103L
     35 # include <bits/c++0x_warning.h>
     36 #else
     37 
     38 #include <bits/c++config.h>
     39 #include <bits/error_constants.h>
     40 #include <iosfwd>
     41 #include <stdexcept>
     42 #if __cplusplus > 201703L
     43 # include <compare>
     44 #endif
     45 
     46 namespace std _GLIBCXX_VISIBILITY(default)
     47 {
     48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     49 
     50   /** @addtogroup diagnostics
     51    * @{
     52    */
     53 
     54   class error_code;
     55   class error_condition;
     56   class system_error;
     57 
     58   /// is_error_code_enum
     59   template<typename _Tp>
     60     struct is_error_code_enum : public false_type { };
     61 
     62   /// is_error_condition_enum
     63   template<typename _Tp>
     64     struct is_error_condition_enum : public false_type { };
     65 
     66   template<>
     67     struct is_error_condition_enum<errc>
     68     : public true_type { };
     69 
     70 #if __cplusplus > 201402L
     71   template <typename _Tp>
     72     inline constexpr bool is_error_code_enum_v =
     73       is_error_code_enum<_Tp>::value;
     74   template <typename _Tp>
     75     inline constexpr bool is_error_condition_enum_v =
     76       is_error_condition_enum<_Tp>::value;
     77 #endif // C++17
     78   /// @}
     79 
     80 _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
     81 
     82   /** @addtogroup diagnostics
     83    * @{
     84    */
     85 
     86   /** Abstract base class for types defining a category of error codes.
     87    *
     88    * An error category defines a context that gives meaning to the integer
     89    * stored in an `error_code` or `error_condition` object. For example,
     90    * the standard `errno` constants such a `EINVAL` and `ENOMEM` are
     91    * associated with the "generic" category and other OS-specific error
     92    * numbers are associated with the "system" category, but a user-defined
     93    * category might give different meanings to the same numerical values.
     94    *
     95    * A user-defined category can override the `equivalent` member functions
     96    * to define correspondence between errors in different categories.
     97    * For example, a category for errors from disk I/O could consider some
     98    * of its error numbers equivalent to ENOSPC and ENOENT in the generic
     99    * category.
    100    *
    101    * @headerfile system_error
    102    * @since C++11
    103    */
    104   class error_category
    105   {
    106   public:
    107     constexpr error_category() noexcept = default;
    108 
    109     virtual ~error_category();
    110 
    111     error_category(const error_category&) = delete;
    112     error_category& operator=(const error_category&) = delete;
    113 
    114     /// A string that identifies the error category.
    115     virtual const char*
    116     name() const noexcept = 0;
    117 
    118     // We need two different virtual functions here, one returning a
    119     // COW string and one returning an SSO string. Their positions in the
    120     // vtable must be consistent for dynamic dispatch to work, but which one
    121     // the name "message()" finds depends on which ABI the caller is using.
    122 #if _GLIBCXX_USE_CXX11_ABI
    123   private:
    124     _GLIBCXX_DEFAULT_ABI_TAG
    125     virtual __cow_string
    126     _M_message(int) const;
    127 
    128   public:
    129     /// A description of the error condition corresponding to the number.
    130     _GLIBCXX_DEFAULT_ABI_TAG
    131     virtual string
    132     message(int) const = 0;
    133 #else
    134     virtual string
    135     message(int) const = 0;
    136 
    137   private:
    138     virtual __sso_string
    139     _M_message(int) const;
    140 #endif
    141 
    142   public:
    143     /// Return an error_condition corresponding to `i` in this category.
    144     virtual error_condition
    145     default_error_condition(int __i) const noexcept;
    146 
    147     /// Test whether `cond` corresponds to `i` for this category.
    148     virtual bool
    149     equivalent(int __i, const error_condition& __cond) const noexcept;
    150 
    151     /// Test whether `code` corresponds to `i` for this category.
    152     virtual bool
    153     equivalent(const error_code& __code, int __i) const noexcept;
    154 
    155     /// An error_category only compares equal to itself.
    156     [[__nodiscard__]]
    157     bool
    158     operator==(const error_category& __other) const noexcept
    159     { return this == &__other; }
    160 
    161     /// Ordered comparison that defines a total order for error categories.
    162 #if __cpp_lib_three_way_comparison
    163     [[nodiscard]]
    164     strong_ordering
    165     operator<=>(const error_category& __rhs) const noexcept
    166     { return std::compare_three_way()(this, &__rhs); }
    167 #else
    168     bool
    169     operator<(const error_category& __other) const noexcept
    170     { return less<const error_category*>()(this, &__other); }
    171 
    172     bool
    173     operator!=(const error_category& __other) const noexcept
    174     { return this != &__other; }
    175 #endif
    176   };
    177 
    178   // DR 890.
    179 
    180   /// Error category for `errno` error codes.
    181   [[__nodiscard__, __gnu__::__const__]]
    182   const error_category&
    183   generic_category() noexcept;
    184 
    185   /// Error category for other error codes defined by the OS.
    186   [[__nodiscard__, __gnu__::__const__]]
    187   const error_category&
    188   system_category() noexcept;
    189 
    190   /// @}
    191 
    192 _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
    193 
    194   /** @addtogroup diagnostics
    195    * @{
    196    */
    197 
    198 namespace __adl_only
    199 {
    200   void make_error_code() = delete;
    201   void make_error_condition() = delete;
    202 }
    203 
    204   /** Class error_code
    205    *
    206    * This class is a value type storing an integer error number and a
    207    * category that gives meaning to the error number. Typically this is done
    208    * close the the point where the error happens, to capture the original
    209    * error value.
    210    *
    211    * An `error_code` object can be used to store the original error value
    212    * emitted by some subsystem, with a category relevant to the subsystem.
    213    * For example, errors from POSIX library functions can be represented by
    214    * an `errno` value and the "generic" category, but errors from an HTTP
    215    * library might be represented by an HTTP response status code (e.g. 404)
    216    * and a custom category defined by the library.
    217    *
    218    * @headerfile system_error
    219    * @since C++11
    220    */
    221   class error_code
    222   {
    223   public:
    224     error_code() noexcept
    225     : _M_value(0), _M_cat(&system_category()) { }
    226 
    227     error_code(int __v, const error_category& __cat) noexcept
    228     : _M_value(__v), _M_cat(&__cat) { }
    229 
    230     template<typename _ErrorCodeEnum, typename = typename
    231 	     enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
    232       error_code(_ErrorCodeEnum __e) noexcept
    233       {
    234 	using __adl_only::make_error_code;
    235 	*this = make_error_code(__e);
    236       }
    237 
    238     void
    239     assign(int __v, const error_category& __cat) noexcept
    240     {
    241       _M_value = __v;
    242       _M_cat = &__cat;
    243     }
    244 
    245     void
    246     clear() noexcept
    247     { assign(0, system_category()); }
    248 
    249     // DR 804.
    250     template<typename _ErrorCodeEnum>
    251       typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
    252 			 error_code&>::type
    253       operator=(_ErrorCodeEnum __e) noexcept
    254       { return *this = make_error_code(__e); }
    255 
    256     /// The error value.
    257     [[__nodiscard__]]
    258     int
    259     value() const noexcept { return _M_value; }
    260 
    261     /// The error category that this error belongs to.
    262     [[__nodiscard__]]
    263     const error_category&
    264     category() const noexcept { return *_M_cat; }
    265 
    266     /// An `error_condition` for this error's category and value.
    267     error_condition
    268     default_error_condition() const noexcept;
    269 
    270     /// The category's description of the value.
    271     _GLIBCXX_DEFAULT_ABI_TAG
    272     string
    273     message() const
    274     { return category().message(value()); }
    275 
    276     /// Test whether `value()` is non-zero.
    277     [[__nodiscard__]]
    278     explicit operator bool() const noexcept
    279     { return _M_value != 0; }
    280 
    281     // DR 804.
    282   private:
    283     int            		_M_value;
    284     const error_category* 	_M_cat;
    285   };
    286 
    287   // C++11 19.5.2.5 non-member functions
    288 
    289   /** Create an `error_code` representing a standard `errc` condition.
    290    *
    291    * The `std::errc` constants correspond to `errno` macros and so use the
    292    * generic category.
    293    *
    294    * @relates error_code
    295    * @since C++11
    296    */
    297   [[__nodiscard__]]
    298   inline error_code
    299   make_error_code(errc __e) noexcept
    300   { return error_code(static_cast<int>(__e), generic_category()); }
    301 
    302   /** Ordered comparison for std::error_code.
    303    *
    304    * This defines a total order by comparing the categories, and then
    305    * if they are equal comparing the values.
    306    *
    307    * @relates error_code
    308    * @since C++11
    309    */
    310 #if __cpp_lib_three_way_comparison
    311   [[nodiscard]]
    312   inline strong_ordering
    313   operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
    314   {
    315     if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
    316       return __c;
    317     return __lhs.value() <=> __rhs.value();
    318   }
    319 #else
    320   inline bool
    321   operator<(const error_code& __lhs, const error_code& __rhs) noexcept
    322   {
    323     return (__lhs.category() < __rhs.category()
    324 	    || (__lhs.category() == __rhs.category()
    325 		&& __lhs.value() < __rhs.value()));
    326   }
    327 #endif
    328 
    329   /** Write a std::error_code to an ostream.
    330    *
    331    * @relates error_code
    332    * @since C++11
    333    */
    334   template<typename _CharT, typename _Traits>
    335     basic_ostream<_CharT, _Traits>&
    336     operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
    337     { return (__os << __e.category().name() << ':' << __e.value()); }
    338 
    339   /** Class error_condition
    340    *
    341    * This class represents error conditions that may be visible at an API
    342    * boundary. Different `error_code` values that can occur within a library
    343    * or module might map to the same `error_condition`.
    344    *
    345    * An `error_condition` represents something that the program can test for,
    346    * and subsequently take appropriate action.
    347    *
    348    * @headerfile system_error
    349    * @since C++11
    350    */
    351   class error_condition
    352   {
    353   public:
    354     /// Initialize with a zero (no error) value and the generic category.
    355     error_condition() noexcept
    356     : _M_value(0), _M_cat(&generic_category()) { }
    357 
    358     /// Initialize with the specified value and category.
    359     error_condition(int __v, const error_category& __cat) noexcept
    360     : _M_value(__v), _M_cat(&__cat) { }
    361 
    362     template<typename _ErrorConditionEnum, typename = typename
    363 	 enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
    364       error_condition(_ErrorConditionEnum __e) noexcept
    365       {
    366 	using __adl_only::make_error_condition;
    367 	*this = make_error_condition(__e);
    368       }
    369 
    370     /// Set the value and category.
    371     void
    372     assign(int __v, const error_category& __cat) noexcept
    373     {
    374       _M_value = __v;
    375       _M_cat = &__cat;
    376     }
    377 
    378     // DR 804.
    379     template<typename _ErrorConditionEnum>
    380       typename enable_if<is_error_condition_enum
    381 			 <_ErrorConditionEnum>::value, error_condition&>::type
    382       operator=(_ErrorConditionEnum __e) noexcept
    383       { return *this = make_error_condition(__e); }
    384 
    385     /// Reset the value and category to the default-constructed state.
    386     void
    387     clear() noexcept
    388     { assign(0, generic_category()); }
    389 
    390     // C++11 19.5.3.4 observers
    391 
    392     /// The error value.
    393     [[__nodiscard__]]
    394     int
    395     value() const noexcept { return _M_value; }
    396 
    397     /// The error category that this error belongs to.
    398     [[__nodiscard__]]
    399     const error_category&
    400     category() const noexcept { return *_M_cat; }
    401 
    402     /// The category's description of the value.
    403     _GLIBCXX_DEFAULT_ABI_TAG
    404     string
    405     message() const
    406     { return category().message(value()); }
    407 
    408     /// Test whether `value()` is non-zero.
    409     [[__nodiscard__]]
    410     explicit operator bool() const noexcept
    411     { return _M_value != 0; }
    412 
    413     // DR 804.
    414   private:
    415     int 			_M_value;
    416     const error_category* 	_M_cat;
    417   };
    418 
    419   // C++11 19.5.3.5 non-member functions
    420 
    421   /** Create an `error_condition` representing a standard `errc` condition.
    422    *
    423    * The `std::errc` constants correspond to `errno` macros and so use the
    424    * generic category.
    425    *
    426    * @relates error_condition
    427    * @since C++11
    428    */
    429   [[__nodiscard__]]
    430   inline error_condition
    431   make_error_condition(errc __e) noexcept
    432   { return error_condition(static_cast<int>(__e), generic_category()); }
    433 
    434   // C++11 19.5.4 Comparison operators
    435 
    436   /** Equality comparison for std::error_code.
    437    *
    438    * Returns true only if they have the same category and the same value.
    439    *
    440    * @relates error_condition
    441    * @since C++11
    442    */
    443   [[__nodiscard__]]
    444   inline bool
    445   operator==(const error_code& __lhs, const error_code& __rhs) noexcept
    446   {
    447     return __lhs.category() == __rhs.category()
    448 	     && __lhs.value() == __rhs.value();
    449   }
    450 
    451   /** Equality comparison for std::error_code and std::error_condition.
    452    *
    453    * Uses each category's `equivalent` member function to check whether
    454    * the values correspond to an equivalent error in that category.
    455    *
    456    * @relates error_condition
    457    * @since C++11
    458    */
    459   [[__nodiscard__]]
    460   inline bool
    461   operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
    462   {
    463     return __lhs.category().equivalent(__lhs.value(), __rhs)
    464 	     || __rhs.category().equivalent(__lhs, __rhs.value());
    465   }
    466 
    467   /** Equality comparison for std::error_condition.
    468    *
    469    * Returns true only if they have the same category and the same value.
    470    *
    471    * @relates error_condition
    472    * @since C++11
    473    */
    474   [[__nodiscard__]]
    475   inline bool
    476   operator==(const error_condition& __lhs,
    477 	     const error_condition& __rhs) noexcept
    478   {
    479     return __lhs.category() == __rhs.category()
    480 	     && __lhs.value() == __rhs.value();
    481   }
    482 
    483   /** Ordered comparison for std::error_condition.
    484    *
    485    * This defines a total order by comparing the categories, and then
    486    * if they are equal comparing the values.
    487    *
    488    * @relates error_condition
    489    * @since C++11
    490    */
    491 #if __cpp_lib_three_way_comparison
    492   [[nodiscard]]
    493   inline strong_ordering
    494   operator<=>(const error_condition& __lhs,
    495 	      const error_condition& __rhs) noexcept
    496   {
    497     if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
    498       return __c;
    499     return __lhs.value() <=> __rhs.value();
    500   }
    501 #else
    502   inline bool
    503   operator<(const error_condition& __lhs,
    504 	    const error_condition& __rhs) noexcept
    505   {
    506     return (__lhs.category() < __rhs.category()
    507 	    || (__lhs.category() == __rhs.category()
    508 		&& __lhs.value() < __rhs.value()));
    509   }
    510 
    511   /// @relates error_condition
    512   inline bool
    513   operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
    514   {
    515     return (__rhs.category().equivalent(__rhs.value(), __lhs)
    516 	    || __lhs.category().equivalent(__rhs, __lhs.value()));
    517   }
    518 
    519   /// @relates error_code
    520   inline bool
    521   operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
    522   { return !(__lhs == __rhs); }
    523 
    524   /// @relates error_code
    525   inline bool
    526   operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
    527   { return !(__lhs == __rhs); }
    528 
    529   /// @relates error_condition
    530   inline bool
    531   operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
    532   { return !(__lhs == __rhs); }
    533 
    534   /// @relates error_condition
    535   inline bool
    536   operator!=(const error_condition& __lhs,
    537 	     const error_condition& __rhs) noexcept
    538   { return !(__lhs == __rhs); }
    539 #endif // three_way_comparison
    540   /// @}
    541 
    542   /**
    543    * @brief An exception type that includes an `error_code` value.
    544    *
    545    * Typically used to report errors from the operating system and other
    546    * low-level APIs.
    547    *
    548    * @headerfile system_error
    549    * @since C++11
    550    * @ingroup exceptions
    551    */
    552   class system_error : public std::runtime_error
    553   {
    554   private:
    555     error_code 	_M_code;
    556 
    557   public:
    558     system_error(error_code __ec = error_code())
    559     : runtime_error(__ec.message()), _M_code(__ec) { }
    560 
    561     system_error(error_code __ec, const string& __what)
    562     : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
    563 
    564     system_error(error_code __ec, const char* __what)
    565     : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
    566 
    567     system_error(int __v, const error_category& __ecat, const char* __what)
    568     : system_error(error_code(__v, __ecat), __what) { }
    569 
    570     system_error(int __v, const error_category& __ecat)
    571     : runtime_error(error_code(__v, __ecat).message()),
    572       _M_code(__v, __ecat) { }
    573 
    574     system_error(int __v, const error_category& __ecat, const string& __what)
    575     : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
    576       _M_code(__v, __ecat) { }
    577 
    578 #if __cplusplus >= 201103L
    579     system_error (const system_error &) = default;
    580     system_error &operator= (const system_error &) = default;
    581 #endif
    582 
    583     virtual ~system_error() noexcept;
    584 
    585     const error_code&
    586     code() const noexcept { return _M_code; }
    587   };
    588 
    589 _GLIBCXX_END_NAMESPACE_VERSION
    590 } // namespace
    591 
    592 #include <bits/functional_hash.h>
    593 
    594 namespace std _GLIBCXX_VISIBILITY(default)
    595 {
    596 _GLIBCXX_BEGIN_NAMESPACE_VERSION
    597 
    598 #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
    599   // DR 1182.
    600   /// std::hash specialization for error_code.
    601   /// @relates error_code
    602   template<>
    603     struct hash<error_code>
    604     : public __hash_base<size_t, error_code>
    605     {
    606       size_t
    607       operator()(const error_code& __e) const noexcept
    608       {
    609 	const size_t __tmp = std::_Hash_impl::hash(__e.value());
    610 	return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
    611       }
    612     };
    613 #endif // _GLIBCXX_COMPATIBILITY_CXX0X
    614 
    615 #if __cplusplus >= 201703L
    616   // DR 2686.
    617   /// std::hash specialization for error_condition.
    618   /// @relates error_condition
    619   template<>
    620     struct hash<error_condition>
    621     : public __hash_base<size_t, error_condition>
    622     {
    623       size_t
    624       operator()(const error_condition& __e) const noexcept
    625       {
    626 	const size_t __tmp = std::_Hash_impl::hash(__e.value());
    627 	return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
    628       }
    629     };
    630 #endif
    631 
    632 _GLIBCXX_END_NAMESPACE_VERSION
    633 } // namespace
    634 
    635 #endif // C++11
    636 
    637 #endif // _GLIBCXX_SYSTEM_ERROR
    638