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