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