libstdc++
system_error
Go to the documentation of this file.
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  inline 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  } // end inline namespace
192 
193  /** @addtogroup diagnostics
194  * @{
195  */
196 
197 namespace __adl_only
198 {
199  void make_error_code() = delete;
200  void make_error_condition() = delete;
201 }
202 
203  /** Class error_code
204  *
205  * This class is a value type storing an integer error number and a
206  * category that gives meaning to the error number. Typically this is done
207  * close the the point where the error happens, to capture the original
208  * error value.
209  *
210  * An `error_code` object can be used to store the original error value
211  * emitted by some subsystem, with a category relevant to the subsystem.
212  * For example, errors from POSIX library functions can be represented by
213  * an `errno` value and the "generic" category, but errors from an HTTP
214  * library might be represented by an HTTP response status code (e.g. 404)
215  * and a custom category defined by the library.
216  *
217  * @headerfile system_error
218  * @since C++11
219  */
220  class error_code
221  {
222  public:
223  error_code() noexcept
224  : _M_value(0), _M_cat(&system_category()) { }
225 
226  error_code(int __v, const error_category& __cat) noexcept
227  : _M_value(__v), _M_cat(&__cat) { }
228 
229  template<typename _ErrorCodeEnum, typename = typename
230  enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
231  error_code(_ErrorCodeEnum __e) noexcept
232  {
233  using __adl_only::make_error_code;
234  *this = make_error_code(__e);
235  }
236 
237  void
238  assign(int __v, const error_category& __cat) noexcept
239  {
240  _M_value = __v;
241  _M_cat = &__cat;
242  }
243 
244  void
245  clear() noexcept
246  { assign(0, system_category()); }
247 
248  // DR 804.
249  template<typename _ErrorCodeEnum>
250  typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
251  error_code&>::type
252  operator=(_ErrorCodeEnum __e) noexcept
253  { return *this = make_error_code(__e); }
254 
255  /// The error value.
256  [[__nodiscard__]]
257  int
258  value() const noexcept { return _M_value; }
259 
260  /// The error category that this error belongs to.
261  [[__nodiscard__]]
262  const error_category&
263  category() const noexcept { return *_M_cat; }
264 
265  /// An `error_condition` for this error's category and value.
266  error_condition
267  default_error_condition() const noexcept;
268 
269  /// The category's description of the value.
270  _GLIBCXX_DEFAULT_ABI_TAG
271  string
272  message() const
273  { return category().message(value()); }
274 
275  /// Test whether `value()` is non-zero.
276  [[__nodiscard__]]
277  explicit operator bool() const noexcept
278  { return _M_value != 0; }
279 
280  // DR 804.
281  private:
282  int _M_value;
283  const error_category* _M_cat;
284  };
285 
286  // C++11 19.5.2.5 non-member functions
287 
288  /** Create an `error_code` representing a standard `errc` condition.
289  *
290  * The `std::errc` constants correspond to `errno` macros and so use the
291  * generic category.
292  *
293  * @relates error_code
294  * @since C++11
295  */
296  [[__nodiscard__]]
297  inline error_code
298  make_error_code(errc __e) noexcept
299  { return error_code(static_cast<int>(__e), generic_category()); }
300 
301  /** Ordered comparison for std::error_code.
302  *
303  * This defines a total order by comparing the categories, and then
304  * if they are equal comparing the values.
305  *
306  * @relates error_code
307  * @since C++11
308  */
309 #if __cpp_lib_three_way_comparison
310  [[nodiscard]]
311  inline strong_ordering
312  operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
313  {
314  if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
315  return __c;
316  return __lhs.value() <=> __rhs.value();
317  }
318 #else
319  inline bool
320  operator<(const error_code& __lhs, const error_code& __rhs) noexcept
321  {
322  return (__lhs.category() < __rhs.category()
323  || (__lhs.category() == __rhs.category()
324  && __lhs.value() < __rhs.value()));
325  }
326 #endif
327 
328  /** Write a std::error_code to an ostream.
329  *
330  * @relates error_code
331  * @since C++11
332  */
333  template<typename _CharT, typename _Traits>
334  basic_ostream<_CharT, _Traits>&
335  operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
336  { return (__os << __e.category().name() << ':' << __e.value()); }
337 
338  /** Class error_condition
339  *
340  * This class represents error conditions that may be visible at an API
341  * boundary. Different `error_code` values that can occur within a library
342  * or module might map to the same `error_condition`.
343  *
344  * An `error_condition` represents something that the program can test for,
345  * and subsequently take appropriate action.
346  *
347  * @headerfile system_error
348  * @since C++11
349  */
350  class error_condition
351  {
352  public:
353  /// Initialize with a zero (no error) value and the generic category.
354  error_condition() noexcept
355  : _M_value(0), _M_cat(&generic_category()) { }
356 
357  /// Initialize with the specified value and category.
358  error_condition(int __v, const error_category& __cat) noexcept
359  : _M_value(__v), _M_cat(&__cat) { }
360 
361  template<typename _ErrorConditionEnum, typename = typename
362  enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
363  error_condition(_ErrorConditionEnum __e) noexcept
364  {
365  using __adl_only::make_error_condition;
366  *this = make_error_condition(__e);
367  }
368 
369  /// Set the value and category.
370  void
371  assign(int __v, const error_category& __cat) noexcept
372  {
373  _M_value = __v;
374  _M_cat = &__cat;
375  }
376 
377  // DR 804.
378  template<typename _ErrorConditionEnum>
379  typename enable_if<is_error_condition_enum
380  <_ErrorConditionEnum>::value, error_condition&>::type
381  operator=(_ErrorConditionEnum __e) noexcept
382  { return *this = make_error_condition(__e); }
383 
384  /// Reset the value and category to the default-constructed state.
385  void
386  clear() noexcept
387  { assign(0, generic_category()); }
388 
389  // C++11 19.5.3.4 observers
390 
391  /// The error value.
392  [[__nodiscard__]]
393  int
394  value() const noexcept { return _M_value; }
395 
396  /// The error category that this error belongs to.
397  [[__nodiscard__]]
398  const error_category&
399  category() const noexcept { return *_M_cat; }
400 
401  /// The category's description of the value.
402  _GLIBCXX_DEFAULT_ABI_TAG
403  string
404  message() const
405  { return category().message(value()); }
406 
407  /// Test whether `value()` is non-zero.
408  [[__nodiscard__]]
409  explicit operator bool() const noexcept
410  { return _M_value != 0; }
411 
412  // DR 804.
413  private:
414  int _M_value;
415  const error_category* _M_cat;
416  };
417 
418  // C++11 19.5.3.5 non-member functions
419 
420  /** Create an `error_condition` representing a standard `errc` condition.
421  *
422  * The `std::errc` constants correspond to `errno` macros and so use the
423  * generic category.
424  *
425  * @relates error_condition
426  * @since C++11
427  */
428  [[__nodiscard__]]
429  inline error_condition
430  make_error_condition(errc __e) noexcept
431  { return error_condition(static_cast<int>(__e), generic_category()); }
432 
433  // C++11 19.5.4 Comparison operators
434 
435  /** Equality comparison for std::error_code.
436  *
437  * Returns true only if they have the same category and the same value.
438  *
439  * @relates error_condition
440  * @since C++11
441  */
442  [[__nodiscard__]]
443  inline bool
444  operator==(const error_code& __lhs, const error_code& __rhs) noexcept
445  {
446  return __lhs.category() == __rhs.category()
447  && __lhs.value() == __rhs.value();
448  }
449 
450  /** Equality comparison for std::error_code and std::error_condition.
451  *
452  * Uses each category's `equivalent` member function to check whether
453  * the values correspond to an equivalent error in that category.
454  *
455  * @relates error_condition
456  * @since C++11
457  */
458  [[__nodiscard__]]
459  inline bool
460  operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
461  {
462  return __lhs.category().equivalent(__lhs.value(), __rhs)
463  || __rhs.category().equivalent(__lhs, __rhs.value());
464  }
465 
466  /** Equality comparison for std::error_condition.
467  *
468  * Returns true only if they have the same category and the same value.
469  *
470  * @relates error_condition
471  * @since C++11
472  */
473  [[__nodiscard__]]
474  inline bool
475  operator==(const error_condition& __lhs,
476  const error_condition& __rhs) noexcept
477  {
478  return __lhs.category() == __rhs.category()
479  && __lhs.value() == __rhs.value();
480  }
481 
482  /** Ordered comparison for std::error_condition.
483  *
484  * This defines a total order by comparing the categories, and then
485  * if they are equal comparing the values.
486  *
487  * @relates error_condition
488  * @since C++11
489  */
490 #if __cpp_lib_three_way_comparison
491  [[nodiscard]]
492  inline strong_ordering
493  operator<=>(const error_condition& __lhs,
494  const error_condition& __rhs) noexcept
495  {
496  if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
497  return __c;
498  return __lhs.value() <=> __rhs.value();
499  }
500 #else
501  inline bool
502  operator<(const error_condition& __lhs,
503  const error_condition& __rhs) noexcept
504  {
505  return (__lhs.category() < __rhs.category()
506  || (__lhs.category() == __rhs.category()
507  && __lhs.value() < __rhs.value()));
508  }
509 
510  /// @relates error_condition
511  inline bool
512  operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
513  {
514  return (__rhs.category().equivalent(__rhs.value(), __lhs)
515  || __lhs.category().equivalent(__rhs, __lhs.value()));
516  }
517 
518  /// @relates error_code
519  inline bool
520  operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
521  { return !(__lhs == __rhs); }
522 
523  /// @relates error_code
524  inline bool
525  operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
526  { return !(__lhs == __rhs); }
527 
528  /// @relates error_condition
529  inline bool
530  operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
531  { return !(__lhs == __rhs); }
532 
533  /// @relates error_condition
534  inline bool
535  operator!=(const error_condition& __lhs,
536  const error_condition& __rhs) noexcept
537  { return !(__lhs == __rhs); }
538 #endif // three_way_comparison
539  /// @}
540 
541  /**
542  * @brief An exception type that includes an `error_code` value.
543  *
544  * Typically used to report errors from the operating system and other
545  * low-level APIs.
546  *
547  * @headerfile system_error
548  * @since C++11
549  * @ingroup exceptions
550  */
551  class system_error : public std::runtime_error
552  {
553  private:
554  error_code _M_code;
555 
556  public:
557  system_error(error_code __ec = error_code())
558  : runtime_error(__ec.message()), _M_code(__ec) { }
559 
560  system_error(error_code __ec, const string& __what)
561  : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
562 
563  system_error(error_code __ec, const char* __what)
564  : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
565 
566  system_error(int __v, const error_category& __ecat, const char* __what)
567  : system_error(error_code(__v, __ecat), __what) { }
568 
569  system_error(int __v, const error_category& __ecat)
570  : runtime_error(error_code(__v, __ecat).message()),
571  _M_code(__v, __ecat) { }
572 
573  system_error(int __v, const error_category& __ecat, const string& __what)
574  : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
575  _M_code(__v, __ecat) { }
576 
577 #if __cplusplus >= 201103L
578  system_error (const system_error &) = default;
579  system_error &operator= (const system_error &) = default;
580 #endif
581 
582  virtual ~system_error() noexcept;
583 
584  const error_code&
585  code() const noexcept { return _M_code; }
586  };
587 
588 _GLIBCXX_END_NAMESPACE_VERSION
589 } // namespace
590 
591 #include <bits/functional_hash.h>
592 
593 namespace std _GLIBCXX_VISIBILITY(default)
594 {
595 _GLIBCXX_BEGIN_NAMESPACE_VERSION
596 
597 #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
598  // DR 1182.
599  /// std::hash specialization for error_code.
600  /// @relates error_code
601  template<>
602  struct hash<error_code>
603  : public __hash_base<size_t, error_code>
604  {
605  size_t
606  operator()(const error_code& __e) const noexcept
607  {
608  const size_t __tmp = std::_Hash_impl::hash(__e.value());
609  return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
610  }
611  };
612 #endif // _GLIBCXX_COMPATIBILITY_CXX0X
613 
614 #if __cplusplus >= 201703L
615  // DR 2686.
616  /// std::hash specialization for error_condition.
617  /// @relates error_condition
618  template<>
619  struct hash<error_condition>
620  : public __hash_base<size_t, error_condition>
621  {
622  size_t
623  operator()(const error_condition& __e) const noexcept
624  {
625  const size_t __tmp = std::_Hash_impl::hash(__e.value());
626  return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
627  }
628  };
629 #endif
630 
631 _GLIBCXX_END_NAMESPACE_VERSION
632 } // namespace
633 
634 #endif // C++11
635 
636 #endif // _GLIBCXX_SYSTEM_ERROR