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