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