1// <system_error> -*- C++ -*- 2 3// Copyright (C) 2007-2018 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#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 43namespace std _GLIBCXX_VISIBILITY(default) 44{ 45_GLIBCXX_BEGIN_NAMESPACE_VERSION 46 47 class error_code; 48 class error_condition; 49 class system_error; 50 51 /// is_error_code_enum 52 template<typename _Tp> 53 struct is_error_code_enum : public false_type { }; 54 55 /// is_error_condition_enum 56 template<typename _Tp> 57 struct is_error_condition_enum : public false_type { }; 58 59 template<> 60 struct is_error_condition_enum<errc> 61 : public true_type { }; 62 63#if __cplusplus > 201402L 64 template <typename _Tp> 65 inline constexpr bool is_error_code_enum_v = 66 is_error_code_enum<_Tp>::value; 67 template <typename _Tp> 68 inline constexpr bool is_error_condition_enum_v = 69 is_error_condition_enum<_Tp>::value; 70#endif // C++17 71 inline namespace _V2 { 72 73 /// error_category 74 class error_category 75 { 76 public: 77 constexpr error_category() noexcept = default; 78 79 virtual ~error_category(); 80 81 error_category(const error_category&) = delete; 82 error_category& operator=(const error_category&) = delete; 83 84 virtual const char* 85 name() const noexcept = 0; 86 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 97 public: 98 _GLIBCXX_DEFAULT_ABI_TAG 99 virtual string 100 message(int) const = 0; 101#else 102 virtual string 103 message(int) const = 0; 104 105 private: 106 virtual __sso_string 107 _M_message(int) const; 108#endif 109 110 public: 111 virtual error_condition 112 default_error_condition(int __i) const noexcept; 113 114 virtual bool 115 equivalent(int __i, const error_condition& __cond) const noexcept; 116 117 virtual bool 118 equivalent(const error_code& __code, int __i) const noexcept; 119 120 bool 121 operator<(const error_category& __other) const noexcept 122 { return less<const error_category*>()(this, &__other); } 123 124 bool 125 operator==(const error_category& __other) const noexcept 126 { return this == &__other; } 127 128 bool 129 operator!=(const error_category& __other) const noexcept 130 { return this != &__other; } 131 }; 132 133 // DR 890. 134 _GLIBCXX_CONST const error_category& system_category() noexcept; 135 _GLIBCXX_CONST const error_category& generic_category() noexcept; 136 137 } // end inline namespace 138 139 error_code make_error_code(errc) noexcept; 140 141 template<typename _Tp> 142 struct hash; 143 144 /// error_code 145 // Implementation-specific error identification 146 struct error_code 147 { 148 error_code() noexcept 149 : _M_value(0), _M_cat(&system_category()) { } 150 151 error_code(int __v, const error_category& __cat) noexcept 152 : _M_value(__v), _M_cat(&__cat) { } 153 154 template<typename _ErrorCodeEnum, typename = typename 155 enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type> 156 error_code(_ErrorCodeEnum __e) noexcept 157 { *this = make_error_code(__e); } 158 159 void 160 assign(int __v, const error_category& __cat) noexcept 161 { 162 _M_value = __v; 163 _M_cat = &__cat; 164 } 165 166 void 167 clear() noexcept 168 { assign(0, system_category()); } 169 170 // DR 804. 171 template<typename _ErrorCodeEnum> 172 typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value, 173 error_code&>::type 174 operator=(_ErrorCodeEnum __e) noexcept 175 { return *this = make_error_code(__e); } 176 177 int 178 value() const noexcept { return _M_value; } 179 180 const error_category& 181 category() const noexcept { return *_M_cat; } 182 183 error_condition 184 default_error_condition() const noexcept; 185 186 _GLIBCXX_DEFAULT_ABI_TAG 187 string 188 message() const 189 { return category().message(value()); } 190 191 explicit operator bool() const noexcept 192 { return _M_value != 0; } 193 194 // DR 804. 195 private: 196 friend class hash<error_code>; 197 198 int _M_value; 199 const error_category* _M_cat; 200 }; 201 202 // 19.4.2.6 non-member functions 203 inline error_code 204 make_error_code(errc __e) noexcept 205 { return error_code(static_cast<int>(__e), generic_category()); } 206 207 inline bool 208 operator<(const error_code& __lhs, const error_code& __rhs) noexcept 209 { 210 return (__lhs.category() < __rhs.category() 211 || (__lhs.category() == __rhs.category() 212 && __lhs.value() < __rhs.value())); 213 } 214 215 template<typename _CharT, typename _Traits> 216 basic_ostream<_CharT, _Traits>& 217 operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e) 218 { return (__os << __e.category().name() << ':' << __e.value()); } 219 220 error_condition make_error_condition(errc) noexcept; 221 222 /// error_condition 223 // Portable error identification 224 struct error_condition 225 { 226 error_condition() noexcept 227 : _M_value(0), _M_cat(&generic_category()) { } 228 229 error_condition(int __v, const error_category& __cat) noexcept 230 : _M_value(__v), _M_cat(&__cat) { } 231 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 237 void 238 assign(int __v, const error_category& __cat) noexcept 239 { 240 _M_value = __v; 241 _M_cat = &__cat; 242 } 243 244 // DR 804. 245 template<typename _ErrorConditionEnum> 246 typename enable_if<is_error_condition_enum 247 <_ErrorConditionEnum>::value, error_condition&>::type 248 operator=(_ErrorConditionEnum __e) noexcept 249 { return *this = make_error_condition(__e); } 250 251 void 252 clear() noexcept 253 { assign(0, generic_category()); } 254 255 // 19.4.3.4 observers 256 int 257 value() const noexcept { return _M_value; } 258 259 const error_category& 260 category() const noexcept { return *_M_cat; } 261 262 _GLIBCXX_DEFAULT_ABI_TAG 263 string 264 message() const 265 { return category().message(value()); } 266 267 explicit operator bool() const noexcept 268 { return _M_value != 0; } 269 270 // DR 804. 271 private: 272 int _M_value; 273 const error_category* _M_cat; 274 }; 275 276 // 19.4.3.6 non-member functions 277 inline error_condition 278 make_error_condition(errc __e) noexcept 279 { return error_condition(static_cast<int>(__e), generic_category()); } 280 281 inline bool 282 operator<(const error_condition& __lhs, 283 const error_condition& __rhs) noexcept 284 { 285 return (__lhs.category() < __rhs.category() 286 || (__lhs.category() == __rhs.category() 287 && __lhs.value() < __rhs.value())); 288 } 289 290 // 19.4.4 Comparison operators 291 inline bool 292 operator==(const error_code& __lhs, const error_code& __rhs) noexcept 293 { return (__lhs.category() == __rhs.category() 294 && __lhs.value() == __rhs.value()); } 295 296 inline bool 297 operator==(const error_code& __lhs, const error_condition& __rhs) noexcept 298 { 299 return (__lhs.category().equivalent(__lhs.value(), __rhs) 300 || __rhs.category().equivalent(__lhs, __rhs.value())); 301 } 302 303 inline bool 304 operator==(const error_condition& __lhs, const error_code& __rhs) noexcept 305 { 306 return (__rhs.category().equivalent(__rhs.value(), __lhs) 307 || __lhs.category().equivalent(__rhs, __lhs.value())); 308 } 309 310 inline bool 311 operator==(const error_condition& __lhs, 312 const error_condition& __rhs) noexcept 313 { 314 return (__lhs.category() == __rhs.category() 315 && __lhs.value() == __rhs.value()); 316 } 317 318 inline bool 319 operator!=(const error_code& __lhs, const error_code& __rhs) noexcept 320 { return !(__lhs == __rhs); } 321 322 inline bool 323 operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept 324 { return !(__lhs == __rhs); } 325 326 inline bool 327 operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept 328 { return !(__lhs == __rhs); } 329 330 inline bool 331 operator!=(const error_condition& __lhs, 332 const error_condition& __rhs) noexcept 333 { return !(__lhs == __rhs); } 334 335 336 /** 337 * @brief Thrown to indicate error code of underlying system. 338 * 339 * @ingroup exceptions 340 */ 341 class system_error : public std::runtime_error 342 { 343 private: 344 error_code _M_code; 345 346 public: 347 system_error(error_code __ec = error_code()) 348 : runtime_error(__ec.message()), _M_code(__ec) { } 349 350 system_error(error_code __ec, const string& __what) 351 : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { } 352 353 system_error(error_code __ec, const char* __what) 354 : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { } 355 356 system_error(int __v, const error_category& __ecat, const char* __what) 357 : system_error(error_code(__v, __ecat), __what) { } 358 359 system_error(int __v, const error_category& __ecat) 360 : runtime_error(error_code(__v, __ecat).message()), 361 _M_code(__v, __ecat) { } 362 363 system_error(int __v, const error_category& __ecat, const string& __what) 364 : runtime_error(__what + ": " + error_code(__v, __ecat).message()), 365 _M_code(__v, __ecat) { } 366 367 virtual ~system_error() noexcept; 368 369 const error_code& 370 code() const noexcept { return _M_code; } 371 }; 372 373_GLIBCXX_END_NAMESPACE_VERSION 374} // namespace 375 376#include <bits/functional_hash.h> 377 378namespace std _GLIBCXX_VISIBILITY(default) 379{ 380_GLIBCXX_BEGIN_NAMESPACE_VERSION 381 382#ifndef _GLIBCXX_COMPATIBILITY_CXX0X 383 // DR 1182. 384 /// std::hash specialization for error_code. 385 template<> 386 struct hash<error_code> 387 : public __hash_base<size_t, error_code> 388 { 389 size_t 390 operator()(const error_code& __e) const noexcept 391 { 392 const size_t __tmp = std::_Hash_impl::hash(__e._M_value); 393 return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp); 394 } 395 }; 396#endif // _GLIBCXX_COMPATIBILITY_CXX0X 397 398#if __cplusplus > 201402L 399 // DR 2686. 400 /// std::hash specialization for error_condition. 401 template<> 402 struct hash<error_condition> 403 : public __hash_base<size_t, error_condition> 404 { 405 size_t 406 operator()(const error_condition& __e) const noexcept 407 { 408 const size_t __tmp = std::_Hash_impl::hash(__e.value()); 409 return std::_Hash_impl::__hash_combine(__e.category(), __tmp); 410 } 411 }; 412#endif 413 414_GLIBCXX_END_NAMESPACE_VERSION 415} // namespace 416 417#endif // C++11 418 419#endif // _GLIBCXX_SYSTEM_ERROR 420