system_error 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. // <system_error> -*- C++ -*-
  2. // Copyright (C) 2007-2022 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file include/system_error
  21. * This is a Standard C++ Library header.
  22. */
  23. #ifndef _GLIBCXX_SYSTEM_ERROR
  24. #define _GLIBCXX_SYSTEM_ERROR 1
  25. #pragma GCC system_header
  26. #if __cplusplus < 201103L
  27. # include <bits/c++0x_warning.h>
  28. #else
  29. #include <bits/c++config.h>
  30. #include <bits/error_constants.h>
  31. #include <iosfwd>
  32. #include <stdexcept>
  33. #if __cplusplus > 201703L
  34. # include <compare>
  35. #endif
  36. namespace std _GLIBCXX_VISIBILITY(default)
  37. {
  38. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  39. /** @addtogroup diagnostics
  40. * @{
  41. */
  42. class error_code;
  43. class error_condition;
  44. class system_error;
  45. /// is_error_code_enum
  46. template<typename _Tp>
  47. struct is_error_code_enum : public false_type { };
  48. /// is_error_condition_enum
  49. template<typename _Tp>
  50. struct is_error_condition_enum : public false_type { };
  51. template<>
  52. struct is_error_condition_enum<errc>
  53. : public true_type { };
  54. #if __cplusplus > 201402L
  55. template <typename _Tp>
  56. inline constexpr bool is_error_code_enum_v =
  57. is_error_code_enum<_Tp>::value;
  58. template <typename _Tp>
  59. inline constexpr bool is_error_condition_enum_v =
  60. is_error_condition_enum<_Tp>::value;
  61. #endif // C++17
  62. /// @}
  63. inline namespace _V2 {
  64. /** @addtogroup diagnostics
  65. * @{
  66. */
  67. /** Abstract base class for types defining a category of error codes.
  68. *
  69. * An error category defines a context that give meaning to the integer
  70. * stored in an `error_code` or `error_condition` object. For example,
  71. * the standard `errno` constants such a `EINVAL` and `ENOMEM` are
  72. * associated with the "generic" category and other OS-specific error
  73. * numbers are associated with the "system" category, but a user-defined
  74. * category might give different meanings to the same numerical values.
  75. *
  76. * @since C++11
  77. */
  78. class error_category
  79. {
  80. public:
  81. constexpr error_category() noexcept = default;
  82. virtual ~error_category();
  83. error_category(const error_category&) = delete;
  84. error_category& operator=(const error_category&) = delete;
  85. virtual const char*
  86. name() const noexcept = 0;
  87. // We need two different virtual functions here, one returning a
  88. // COW string and one returning an SSO string. Their positions in the
  89. // vtable must be consistent for dynamic dispatch to work, but which one
  90. // the name "message()" finds depends on which ABI the caller is using.
  91. #if _GLIBCXX_USE_CXX11_ABI
  92. private:
  93. _GLIBCXX_DEFAULT_ABI_TAG
  94. virtual __cow_string
  95. _M_message(int) const;
  96. public:
  97. _GLIBCXX_DEFAULT_ABI_TAG
  98. virtual string
  99. message(int) const = 0;
  100. #else
  101. virtual string
  102. message(int) const = 0;
  103. private:
  104. virtual __sso_string
  105. _M_message(int) const;
  106. #endif
  107. public:
  108. virtual error_condition
  109. default_error_condition(int __i) const noexcept;
  110. virtual bool
  111. equivalent(int __i, const error_condition& __cond) const noexcept;
  112. virtual bool
  113. equivalent(const error_code& __code, int __i) const noexcept;
  114. bool
  115. operator==(const error_category& __other) const noexcept
  116. { return this == &__other; }
  117. #if __cpp_lib_three_way_comparison
  118. strong_ordering
  119. operator<=>(const error_category& __rhs) const noexcept
  120. { return std::compare_three_way()(this, &__rhs); }
  121. #else
  122. bool
  123. operator!=(const error_category& __other) const noexcept
  124. { return this != &__other; }
  125. bool
  126. operator<(const error_category& __other) const noexcept
  127. { return less<const error_category*>()(this, &__other); }
  128. #endif
  129. };
  130. // DR 890.
  131. /// Error category for `errno` error codes.
  132. _GLIBCXX_CONST const error_category& generic_category() noexcept;
  133. /// Error category for other error codes defined by the OS.
  134. _GLIBCXX_CONST const error_category& system_category() noexcept;
  135. /// @}
  136. } // end inline namespace
  137. /** @addtogroup diagnostics
  138. * @{
  139. */
  140. error_code make_error_code(errc) noexcept;
  141. /** Class error_code
  142. *
  143. * This class is a value type storing an integer error number and a
  144. * category that gives meaning to the error number. Typically this is done
  145. * close the the point where the error happens, to capture the original
  146. * error value.
  147. *
  148. * An `error_code` object can be used to store the original error value
  149. * emitted by some subsystem, with a category relevant to the subsystem.
  150. * For example, errors from POSIX library functions can be represented by
  151. * an `errno` value and the "generic" category, but errors from an HTTP
  152. * library might be represented by an HTTP response status code (e.g. 404)
  153. * and a custom category defined by the library.
  154. *
  155. * @since C++11
  156. * @ingroup diagnostics
  157. */
  158. class error_code
  159. {
  160. public:
  161. error_code() noexcept
  162. : _M_value(0), _M_cat(&system_category()) { }
  163. error_code(int __v, const error_category& __cat) noexcept
  164. : _M_value(__v), _M_cat(&__cat) { }
  165. template<typename _ErrorCodeEnum, typename = typename
  166. enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
  167. error_code(_ErrorCodeEnum __e) noexcept
  168. { *this = make_error_code(__e); }
  169. void
  170. assign(int __v, const error_category& __cat) noexcept
  171. {
  172. _M_value = __v;
  173. _M_cat = &__cat;
  174. }
  175. void
  176. clear() noexcept
  177. { assign(0, system_category()); }
  178. // DR 804.
  179. template<typename _ErrorCodeEnum>
  180. typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
  181. error_code&>::type
  182. operator=(_ErrorCodeEnum __e) noexcept
  183. { return *this = make_error_code(__e); }
  184. int
  185. value() const noexcept { return _M_value; }
  186. const error_category&
  187. category() const noexcept { return *_M_cat; }
  188. error_condition
  189. default_error_condition() const noexcept;
  190. _GLIBCXX_DEFAULT_ABI_TAG
  191. string
  192. message() const
  193. { return category().message(value()); }
  194. explicit operator bool() const noexcept
  195. { return _M_value != 0; }
  196. // DR 804.
  197. private:
  198. int _M_value;
  199. const error_category* _M_cat;
  200. };
  201. // 19.4.2.6 non-member functions
  202. /// @relates error_code @{
  203. inline error_code
  204. make_error_code(errc __e) noexcept
  205. { return error_code(static_cast<int>(__e), generic_category()); }
  206. #if __cpp_lib_three_way_comparison
  207. inline strong_ordering
  208. operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
  209. {
  210. if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
  211. return __c;
  212. return __lhs.value() <=> __rhs.value();
  213. }
  214. #else
  215. inline bool
  216. operator<(const error_code& __lhs, const error_code& __rhs) noexcept
  217. {
  218. return (__lhs.category() < __rhs.category()
  219. || (__lhs.category() == __rhs.category()
  220. && __lhs.value() < __rhs.value()));
  221. }
  222. #endif
  223. template<typename _CharT, typename _Traits>
  224. basic_ostream<_CharT, _Traits>&
  225. operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
  226. { return (__os << __e.category().name() << ':' << __e.value()); }
  227. /// @}
  228. error_condition make_error_condition(errc) noexcept;
  229. /** Class error_condition
  230. *
  231. * This class represents error conditions that may be visible at an API
  232. * boundary. Different `error_code` values that can occur within a library
  233. * or module might map to the same `error_condition`.
  234. *
  235. * An `error_condition` represents something that the program can test for,
  236. * and subsequently take appropriate action.
  237. *
  238. * @since C++11
  239. */
  240. class error_condition
  241. {
  242. public:
  243. error_condition() noexcept
  244. : _M_value(0), _M_cat(&generic_category()) { }
  245. error_condition(int __v, const error_category& __cat) noexcept
  246. : _M_value(__v), _M_cat(&__cat) { }
  247. template<typename _ErrorConditionEnum, typename = typename
  248. enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
  249. error_condition(_ErrorConditionEnum __e) noexcept
  250. { *this = make_error_condition(__e); }
  251. void
  252. assign(int __v, const error_category& __cat) noexcept
  253. {
  254. _M_value = __v;
  255. _M_cat = &__cat;
  256. }
  257. // DR 804.
  258. template<typename _ErrorConditionEnum>
  259. typename enable_if<is_error_condition_enum
  260. <_ErrorConditionEnum>::value, error_condition&>::type
  261. operator=(_ErrorConditionEnum __e) noexcept
  262. { return *this = make_error_condition(__e); }
  263. void
  264. clear() noexcept
  265. { assign(0, generic_category()); }
  266. // 19.4.3.4 observers
  267. int
  268. value() const noexcept { return _M_value; }
  269. const error_category&
  270. category() const noexcept { return *_M_cat; }
  271. _GLIBCXX_DEFAULT_ABI_TAG
  272. string
  273. message() const
  274. { return category().message(value()); }
  275. explicit operator bool() const noexcept
  276. { return _M_value != 0; }
  277. // DR 804.
  278. private:
  279. int _M_value;
  280. const error_category* _M_cat;
  281. };
  282. // 19.4.3.6 non-member functions
  283. /// Create an `error_condition` representing a standard `errc` condition.
  284. /// @relates error_condition
  285. inline error_condition
  286. make_error_condition(errc __e) noexcept
  287. { return error_condition(static_cast<int>(__e), generic_category()); }
  288. // 19.4.4 Comparison operators
  289. /// @relates error_code
  290. inline bool
  291. operator==(const error_code& __lhs, const error_code& __rhs) noexcept
  292. { return (__lhs.category() == __rhs.category()
  293. && __lhs.value() == __rhs.value()); }
  294. /// @relates error_code
  295. inline bool
  296. operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
  297. {
  298. return (__lhs.category().equivalent(__lhs.value(), __rhs)
  299. || __rhs.category().equivalent(__lhs, __rhs.value()));
  300. }
  301. /// @relates error_condition
  302. inline bool
  303. operator==(const error_condition& __lhs,
  304. const error_condition& __rhs) noexcept
  305. {
  306. return (__lhs.category() == __rhs.category()
  307. && __lhs.value() == __rhs.value());
  308. }
  309. #if __cpp_lib_three_way_comparison
  310. /// Define an ordering for error_condition objects.
  311. /// @relates error_condition
  312. inline strong_ordering
  313. operator<=>(const error_condition& __lhs,
  314. const error_condition& __rhs) noexcept
  315. {
  316. if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
  317. return __c;
  318. return __lhs.value() <=> __rhs.value();
  319. }
  320. #else
  321. /// Define an ordering for error_condition objects.
  322. /// @relates error_condition
  323. inline bool
  324. operator<(const error_condition& __lhs,
  325. const error_condition& __rhs) noexcept
  326. {
  327. return (__lhs.category() < __rhs.category()
  328. || (__lhs.category() == __rhs.category()
  329. && __lhs.value() < __rhs.value()));
  330. }
  331. /// @relates error_condition
  332. inline bool
  333. operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
  334. {
  335. return (__rhs.category().equivalent(__rhs.value(), __lhs)
  336. || __lhs.category().equivalent(__rhs, __lhs.value()));
  337. }
  338. /// @relates error_code
  339. inline bool
  340. operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
  341. { return !(__lhs == __rhs); }
  342. /// @relates error_code
  343. inline bool
  344. operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
  345. { return !(__lhs == __rhs); }
  346. /// @relates error_condition
  347. inline bool
  348. operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
  349. { return !(__lhs == __rhs); }
  350. /// @relates error_condition
  351. inline bool
  352. operator!=(const error_condition& __lhs,
  353. const error_condition& __rhs) noexcept
  354. { return !(__lhs == __rhs); }
  355. #endif // three_way_comparison
  356. /// @}
  357. /**
  358. * @brief An exception type that includes an `error_code` value.
  359. *
  360. * Typically used to report errors from the operating system and other
  361. * low-level APIs.
  362. *
  363. * @since C++11
  364. * @ingroup exceptions
  365. */
  366. class system_error : public std::runtime_error
  367. {
  368. private:
  369. error_code _M_code;
  370. public:
  371. system_error(error_code __ec = error_code())
  372. : runtime_error(__ec.message()), _M_code(__ec) { }
  373. system_error(error_code __ec, const string& __what)
  374. : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
  375. system_error(error_code __ec, const char* __what)
  376. : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
  377. system_error(int __v, const error_category& __ecat, const char* __what)
  378. : system_error(error_code(__v, __ecat), __what) { }
  379. system_error(int __v, const error_category& __ecat)
  380. : runtime_error(error_code(__v, __ecat).message()),
  381. _M_code(__v, __ecat) { }
  382. system_error(int __v, const error_category& __ecat, const string& __what)
  383. : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
  384. _M_code(__v, __ecat) { }
  385. #if __cplusplus >= 201103L
  386. system_error (const system_error &) = default;
  387. system_error &operator= (const system_error &) = default;
  388. #endif
  389. virtual ~system_error() noexcept;
  390. const error_code&
  391. code() const noexcept { return _M_code; }
  392. };
  393. _GLIBCXX_END_NAMESPACE_VERSION
  394. } // namespace
  395. #include <bits/functional_hash.h>
  396. namespace std _GLIBCXX_VISIBILITY(default)
  397. {
  398. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  399. #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
  400. // DR 1182.
  401. /// std::hash specialization for error_code.
  402. /// @relates error_code
  403. template<>
  404. struct hash<error_code>
  405. : public __hash_base<size_t, error_code>
  406. {
  407. size_t
  408. operator()(const error_code& __e) const noexcept
  409. {
  410. const size_t __tmp = std::_Hash_impl::hash(__e.value());
  411. return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
  412. }
  413. };
  414. #endif // _GLIBCXX_COMPATIBILITY_CXX0X
  415. #if __cplusplus >= 201703L
  416. // DR 2686.
  417. /// std::hash specialization for error_condition.
  418. /// @relates error_condition
  419. template<>
  420. struct hash<error_condition>
  421. : public __hash_base<size_t, error_condition>
  422. {
  423. size_t
  424. operator()(const error_condition& __e) const noexcept
  425. {
  426. const size_t __tmp = std::_Hash_impl::hash(__e.value());
  427. return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
  428. }
  429. };
  430. #endif
  431. _GLIBCXX_END_NAMESPACE_VERSION
  432. } // namespace
  433. #endif // C++11
  434. #endif // _GLIBCXX_SYSTEM_ERROR