system_error 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. // <system_error> -*- C++ -*-
  2. // Copyright (C) 2007-2021 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. inline namespace _V2 {
  63. /** Abstract base class for types defining a category of error codes.
  64. *
  65. * An error category defines a context that give meaning to the integer
  66. * stored in an `error_code` or `error_condition` object. For example,
  67. * the standard `errno` constants such a `EINVAL` and `ENOMEM` are
  68. * associated with the "generic" category and other OS-specific error
  69. * numbers are associated with the "system" category, but a user-defined
  70. * category might give different meanings to the same numerical values.
  71. */
  72. class error_category
  73. {
  74. public:
  75. constexpr error_category() noexcept = default;
  76. virtual ~error_category();
  77. error_category(const error_category&) = delete;
  78. error_category& operator=(const error_category&) = delete;
  79. virtual const char*
  80. name() const noexcept = 0;
  81. // We need two different virtual functions here, one returning a
  82. // COW string and one returning an SSO string. Their positions in the
  83. // vtable must be consistent for dynamic dispatch to work, but which one
  84. // the name "message()" finds depends on which ABI the caller is using.
  85. #if _GLIBCXX_USE_CXX11_ABI
  86. private:
  87. _GLIBCXX_DEFAULT_ABI_TAG
  88. virtual __cow_string
  89. _M_message(int) const;
  90. public:
  91. _GLIBCXX_DEFAULT_ABI_TAG
  92. virtual string
  93. message(int) const = 0;
  94. #else
  95. virtual string
  96. message(int) const = 0;
  97. private:
  98. virtual __sso_string
  99. _M_message(int) const;
  100. #endif
  101. public:
  102. virtual error_condition
  103. default_error_condition(int __i) const noexcept;
  104. virtual bool
  105. equivalent(int __i, const error_condition& __cond) const noexcept;
  106. virtual bool
  107. equivalent(const error_code& __code, int __i) const noexcept;
  108. bool
  109. operator==(const error_category& __other) const noexcept
  110. { return this == &__other; }
  111. #if __cpp_lib_three_way_comparison
  112. strong_ordering
  113. operator<=>(const error_category& __rhs) const noexcept
  114. { return std::compare_three_way()(this, &__rhs); }
  115. #else
  116. bool
  117. operator!=(const error_category& __other) const noexcept
  118. { return this != &__other; }
  119. bool
  120. operator<(const error_category& __other) const noexcept
  121. { return less<const error_category*>()(this, &__other); }
  122. #endif
  123. };
  124. // DR 890.
  125. /// Error category for `errno` error codes.
  126. _GLIBCXX_CONST const error_category& generic_category() noexcept;
  127. /// Error category for other error codes defined by the OS.
  128. _GLIBCXX_CONST const error_category& system_category() noexcept;
  129. } // end inline namespace
  130. error_code make_error_code(errc) noexcept;
  131. /** Class error_code
  132. *
  133. * This class is a value type storing an integer error number and a
  134. * category that gives meaning to the error number. Typically this is done
  135. * close the the point where the error happens, to capture the original
  136. * error value.
  137. *
  138. * An `error_code` object can be used to store the original error value
  139. * emitted by some subsystem, with a category relevant to the subsystem.
  140. * For example, errors from POSIX library functions can be represented by
  141. * an `errno` value and the "generic" category, but errors from an HTTP
  142. * library might be represented by an HTTP response status code (e.g. 404)
  143. * and a custom category defined by the library.
  144. */
  145. class error_code
  146. {
  147. public:
  148. error_code() noexcept
  149. : _M_value(0), _M_cat(&system_category()) { }
  150. error_code(int __v, const error_category& __cat) noexcept
  151. : _M_value(__v), _M_cat(&__cat) { }
  152. template<typename _ErrorCodeEnum, typename = typename
  153. enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
  154. error_code(_ErrorCodeEnum __e) noexcept
  155. { *this = make_error_code(__e); }
  156. void
  157. assign(int __v, const error_category& __cat) noexcept
  158. {
  159. _M_value = __v;
  160. _M_cat = &__cat;
  161. }
  162. void
  163. clear() noexcept
  164. { assign(0, system_category()); }
  165. // DR 804.
  166. template<typename _ErrorCodeEnum>
  167. typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
  168. error_code&>::type
  169. operator=(_ErrorCodeEnum __e) noexcept
  170. { return *this = make_error_code(__e); }
  171. int
  172. value() const noexcept { return _M_value; }
  173. const error_category&
  174. category() const noexcept { return *_M_cat; }
  175. error_condition
  176. default_error_condition() const noexcept;
  177. _GLIBCXX_DEFAULT_ABI_TAG
  178. string
  179. message() const
  180. { return category().message(value()); }
  181. explicit operator bool() const noexcept
  182. { return _M_value != 0; }
  183. // DR 804.
  184. private:
  185. int _M_value;
  186. const error_category* _M_cat;
  187. };
  188. // 19.4.2.6 non-member functions
  189. /// @relates error_code @{
  190. inline error_code
  191. make_error_code(errc __e) noexcept
  192. { return error_code(static_cast<int>(__e), generic_category()); }
  193. #if __cpp_lib_three_way_comparison
  194. inline strong_ordering
  195. operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
  196. {
  197. if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
  198. return __c;
  199. return __lhs.value() <=> __rhs.value();
  200. }
  201. #else
  202. inline bool
  203. operator<(const error_code& __lhs, const error_code& __rhs) noexcept
  204. {
  205. return (__lhs.category() < __rhs.category()
  206. || (__lhs.category() == __rhs.category()
  207. && __lhs.value() < __rhs.value()));
  208. }
  209. #endif
  210. template<typename _CharT, typename _Traits>
  211. basic_ostream<_CharT, _Traits>&
  212. operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
  213. { return (__os << __e.category().name() << ':' << __e.value()); }
  214. /// @}
  215. error_condition make_error_condition(errc) noexcept;
  216. /** Class error_condition
  217. *
  218. * This class represents error conditions that may be visible at an API
  219. * boundary. Different `error_code` values that can occur within a library
  220. * or module might map to the same `error_condition`.
  221. *
  222. * An `error_condition` represents something that the program can test for,
  223. * and subsequently take appropriate action.
  224. */
  225. class error_condition
  226. {
  227. public:
  228. error_condition() noexcept
  229. : _M_value(0), _M_cat(&generic_category()) { }
  230. error_condition(int __v, const error_category& __cat) noexcept
  231. : _M_value(__v), _M_cat(&__cat) { }
  232. template<typename _ErrorConditionEnum, typename = typename
  233. enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
  234. error_condition(_ErrorConditionEnum __e) noexcept
  235. { *this = make_error_condition(__e); }
  236. void
  237. assign(int __v, const error_category& __cat) noexcept
  238. {
  239. _M_value = __v;
  240. _M_cat = &__cat;
  241. }
  242. // DR 804.
  243. template<typename _ErrorConditionEnum>
  244. typename enable_if<is_error_condition_enum
  245. <_ErrorConditionEnum>::value, error_condition&>::type
  246. operator=(_ErrorConditionEnum __e) noexcept
  247. { return *this = make_error_condition(__e); }
  248. void
  249. clear() noexcept
  250. { assign(0, generic_category()); }
  251. // 19.4.3.4 observers
  252. int
  253. value() const noexcept { return _M_value; }
  254. const error_category&
  255. category() const noexcept { return *_M_cat; }
  256. _GLIBCXX_DEFAULT_ABI_TAG
  257. string
  258. message() const
  259. { return category().message(value()); }
  260. explicit operator bool() const noexcept
  261. { return _M_value != 0; }
  262. // DR 804.
  263. private:
  264. int _M_value;
  265. const error_category* _M_cat;
  266. };
  267. // 19.4.3.6 non-member functions
  268. /// Create an `error_condition` representing a standard `errc` condition.
  269. /// @relates error_condition
  270. inline error_condition
  271. make_error_condition(errc __e) noexcept
  272. { return error_condition(static_cast<int>(__e), generic_category()); }
  273. // 19.4.4 Comparison operators
  274. /// @relates error_code
  275. inline bool
  276. operator==(const error_code& __lhs, const error_code& __rhs) noexcept
  277. { return (__lhs.category() == __rhs.category()
  278. && __lhs.value() == __rhs.value()); }
  279. /// @relates error_code
  280. /// @relates error_condition
  281. inline bool
  282. operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
  283. {
  284. return (__lhs.category().equivalent(__lhs.value(), __rhs)
  285. || __rhs.category().equivalent(__lhs, __rhs.value()));
  286. }
  287. /// @relates error_condition
  288. inline bool
  289. operator==(const error_condition& __lhs,
  290. const error_condition& __rhs) noexcept
  291. {
  292. return (__lhs.category() == __rhs.category()
  293. && __lhs.value() == __rhs.value());
  294. }
  295. #if __cpp_lib_three_way_comparison
  296. /// Define an ordering for error_condition objects.
  297. /// @relates error_condition
  298. inline strong_ordering
  299. operator<=>(const error_condition& __lhs,
  300. const error_condition& __rhs) noexcept
  301. {
  302. if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
  303. return __c;
  304. return __lhs.value() <=> __rhs.value();
  305. }
  306. #else
  307. /// Define an ordering for error_condition objects.
  308. /// @relates error_condition
  309. inline bool
  310. operator<(const error_condition& __lhs,
  311. const error_condition& __rhs) noexcept
  312. {
  313. return (__lhs.category() < __rhs.category()
  314. || (__lhs.category() == __rhs.category()
  315. && __lhs.value() < __rhs.value()));
  316. }
  317. /// @relates error_code
  318. /// @relates error_condition
  319. inline bool
  320. operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
  321. {
  322. return (__rhs.category().equivalent(__rhs.value(), __lhs)
  323. || __lhs.category().equivalent(__rhs, __lhs.value()));
  324. }
  325. /// @relates error_code
  326. inline bool
  327. operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
  328. { return !(__lhs == __rhs); }
  329. /// @relates error_code
  330. /// @relates error_condition
  331. inline bool
  332. operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
  333. { return !(__lhs == __rhs); }
  334. /// @relates error_code
  335. /// @relates error_condition
  336. inline bool
  337. operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
  338. { return !(__lhs == __rhs); }
  339. /// @relates error_condition
  340. inline bool
  341. operator!=(const error_condition& __lhs,
  342. const error_condition& __rhs) noexcept
  343. { return !(__lhs == __rhs); }
  344. #endif // three_way_comparison
  345. /**
  346. * @brief An exception type that includes an `error_code` value.
  347. *
  348. * Typically used to report errors from the operating system and other
  349. * low-level APIs.
  350. *
  351. * @ingroup exceptions
  352. */
  353. class system_error : public std::runtime_error
  354. {
  355. private:
  356. error_code _M_code;
  357. public:
  358. system_error(error_code __ec = error_code())
  359. : runtime_error(__ec.message()), _M_code(__ec) { }
  360. system_error(error_code __ec, const string& __what)
  361. : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
  362. system_error(error_code __ec, const char* __what)
  363. : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
  364. system_error(int __v, const error_category& __ecat, const char* __what)
  365. : system_error(error_code(__v, __ecat), __what) { }
  366. system_error(int __v, const error_category& __ecat)
  367. : runtime_error(error_code(__v, __ecat).message()),
  368. _M_code(__v, __ecat) { }
  369. system_error(int __v, const error_category& __ecat, const string& __what)
  370. : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
  371. _M_code(__v, __ecat) { }
  372. #if __cplusplus >= 201103L
  373. system_error (const system_error &) = default;
  374. system_error &operator= (const system_error &) = default;
  375. #endif
  376. virtual ~system_error() noexcept;
  377. const error_code&
  378. code() const noexcept { return _M_code; }
  379. };
  380. _GLIBCXX_END_NAMESPACE_VERSION
  381. } // namespace
  382. #include <bits/functional_hash.h>
  383. namespace std _GLIBCXX_VISIBILITY(default)
  384. {
  385. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  386. #ifndef _GLIBCXX_COMPATIBILITY_CXX0X
  387. // DR 1182.
  388. /// std::hash specialization for error_code.
  389. /// @relates error_code
  390. template<>
  391. struct hash<error_code>
  392. : public __hash_base<size_t, error_code>
  393. {
  394. size_t
  395. operator()(const error_code& __e) const noexcept
  396. {
  397. const size_t __tmp = std::_Hash_impl::hash(__e.value());
  398. return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
  399. }
  400. };
  401. #endif // _GLIBCXX_COMPATIBILITY_CXX0X
  402. #if __cplusplus >= 201703L
  403. // DR 2686.
  404. /// std::hash specialization for error_condition.
  405. /// @relates error_condition
  406. template<>
  407. struct hash<error_condition>
  408. : public __hash_base<size_t, error_condition>
  409. {
  410. size_t
  411. operator()(const error_condition& __e) const noexcept
  412. {
  413. const size_t __tmp = std::_Hash_impl::hash(__e.value());
  414. return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
  415. }
  416. };
  417. #endif
  418. _GLIBCXX_END_NAMESPACE_VERSION
  419. } // namespace
  420. #endif // C++11
  421. #endif // _GLIBCXX_SYSTEM_ERROR