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