1// boost/system/error_code.hpp -------------------------------------------------------//
2
3// Copyright Beman Dawes 2006, 2007
4// Copyright Christoper Kohlhoff 2007
5// Copyright Peter Dimov 2017, 2018
6
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10// See library home page at http://www.boost.org/libs/system
11
12#ifndef BOOST_SYSTEM_ERROR_CODE_HPP
13#define BOOST_SYSTEM_ERROR_CODE_HPP
14
15#include <boost/system/config.hpp>
16#include <boost/cstdint.hpp>
17#include <boost/assert.hpp>
18#include <boost/noncopyable.hpp>
19#include <boost/utility/enable_if.hpp>
20#include <ostream>
21#include <string>
22#include <stdexcept>
23#include <functional>
24
25// TODO: undef these macros if not already defined
26#include <boost/cerrno.hpp>
27
28#if !defined(BOOST_POSIX_API) && !defined(BOOST_WINDOWS_API)
29# error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined
30#endif
31
32#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
33#include <system_error>
34#endif
35
36#include <boost/config/abi_prefix.hpp> // must be the last #include
37
38#ifndef BOOST_SYSTEM_NOEXCEPT
39#define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT
40#endif
41
42namespace boost
43{
44 namespace system
45 {
46
47 class error_code; // values defined by the operating system
48 class error_condition; // portable generic values defined below, but ultimately
49 // based on the POSIX standard
50
51 // "Concept" helpers -------------------------------------------------------------//
52
53 template< class T >
54 struct is_error_code_enum { static const bool value = false; };
55
56 template< class T >
57 struct is_error_condition_enum { static const bool value = false; };
58
59 // generic error_conditions ------------------------------------------------------//
60
61 namespace errc
62 {
63 enum errc_t
64 {
65 success = 0,
66 address_family_not_supported = EAFNOSUPPORT,
67 address_in_use = EADDRINUSE,
68 address_not_available = EADDRNOTAVAIL,
69 already_connected = EISCONN,
70 argument_list_too_long = E2BIG,
71 argument_out_of_domain = EDOM,
72 bad_address = EFAULT,
73 bad_file_descriptor = EBADF,
74 bad_message = EBADMSG,
75 broken_pipe = EPIPE,
76 connection_aborted = ECONNABORTED,
77 connection_already_in_progress = EALREADY,
78 connection_refused = ECONNREFUSED,
79 connection_reset = ECONNRESET,
80 cross_device_link = EXDEV,
81 destination_address_required = EDESTADDRREQ,
82 device_or_resource_busy = EBUSY,
83 directory_not_empty = ENOTEMPTY,
84 executable_format_error = ENOEXEC,
85 file_exists = EEXIST,
86 file_too_large = EFBIG,
87 filename_too_long = ENAMETOOLONG,
88 function_not_supported = ENOSYS,
89 host_unreachable = EHOSTUNREACH,
90 identifier_removed = EIDRM,
91 illegal_byte_sequence = EILSEQ,
92 inappropriate_io_control_operation = ENOTTY,
93 interrupted = EINTR,
94 invalid_argument = EINVAL,
95 invalid_seek = ESPIPE,
96 io_error = EIO,
97 is_a_directory = EISDIR,
98 message_size = EMSGSIZE,
99 network_down = ENETDOWN,
100 network_reset = ENETRESET,
101 network_unreachable = ENETUNREACH,
102 no_buffer_space = ENOBUFS,
103 no_child_process = ECHILD,
104 no_link = ENOLINK,
105 no_lock_available = ENOLCK,
106 no_message_available = ENODATA,
107 no_message = ENOMSG,
108 no_protocol_option = ENOPROTOOPT,
109 no_space_on_device = ENOSPC,
110 no_stream_resources = ENOSR,
111 no_such_device_or_address = ENXIO,
112 no_such_device = ENODEV,
113 no_such_file_or_directory = ENOENT,
114 no_such_process = ESRCH,
115 not_a_directory = ENOTDIR,
116 not_a_socket = ENOTSOCK,
117 not_a_stream = ENOSTR,
118 not_connected = ENOTCONN,
119 not_enough_memory = ENOMEM,
120 not_supported = ENOTSUP,
121 operation_canceled = ECANCELED,
122 operation_in_progress = EINPROGRESS,
123 operation_not_permitted = EPERM,
124 operation_not_supported = EOPNOTSUPP,
125 operation_would_block = EWOULDBLOCK,
126 owner_dead = EOWNERDEAD,
127 permission_denied = EACCES,
128 protocol_error = EPROTO,
129 protocol_not_supported = EPROTONOSUPPORT,
130 read_only_file_system = EROFS,
131 resource_deadlock_would_occur = EDEADLK,
132 resource_unavailable_try_again = EAGAIN,
133 result_out_of_range = ERANGE,
134 state_not_recoverable = ENOTRECOVERABLE,
135 stream_timeout = ETIME,
136 text_file_busy = ETXTBSY,
137 timed_out = ETIMEDOUT,
138 too_many_files_open_in_system = ENFILE,
139 too_many_files_open = EMFILE,
140 too_many_links = EMLINK,
141 too_many_symbolic_link_levels = ELOOP,
142 value_too_large = EOVERFLOW,
143 wrong_protocol_type = EPROTOTYPE
144 };
145
146 } // namespace errc
147
148# ifdef BOOST_SYSTEM_ENABLE_DEPRECATED
149 namespace posix = errc;
150 namespace posix_error = errc;
151# endif
152
153 template<> struct is_error_condition_enum<errc::errc_t>
154 { static const bool value = true; };
155
156
157 // --------------------------------------------------------------------------------//
158
159 // Operating system specific interfaces ------------------------------------------//
160
161
162 // The interface is divided into general and system-specific portions to
163 // meet these requirements:
164 //
165 // * Code calling an operating system API can create an error_code with
166 // a single category (system_category), even for POSIX-like operating
167 // systems that return some POSIX errno values and some native errno
168 // values. This code should not have to pay the cost of distinguishing
169 // between categories, since it is not yet known if that is needed.
170 //
171 // * Users wishing to write system-specific code should be given enums for
172 // at least the common error cases.
173 //
174 // * System specific code should fail at compile time if moved to another
175 // operating system.
176
177 // The system specific portions of the interface are located in headers
178 // with names reflecting the operating system. For example,
179 //
180 // <boost/system/cygwin_error.hpp>
181 // <boost/system/linux_error.hpp>
182 // <boost/system/windows_error.hpp>
183 //
184 // These headers are effectively empty for compiles on operating systems
185 // where they are not applicable.
186
187 // --------------------------------------------------------------------------------//
188
189 class error_category;
190
191 // predefined error categories ---------------------------------------------------//
192
193#ifdef BOOST_ERROR_CODE_HEADER_ONLY
194 inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT;
195 inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT;
196#else
197 BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT;
198 BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT;
199#endif
200 // deprecated synonyms ------------------------------------------------------------//
201
202#ifdef BOOST_SYSTEM_ENABLE_DEPRECATED
203 inline const error_category & get_system_category() { return system_category(); }
204 inline const error_category & get_generic_category() { return generic_category(); }
205 inline const error_category & get_posix_category() { return generic_category(); }
206 static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED
207 = generic_category();
208 static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED
209 = generic_category();
210 static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED
211 = system_category();
212#endif
213
214#ifdef BOOST_MSVC
215#pragma warning(push)
216// 'this' : used in base member initializer list
217#pragma warning(disable: 4355)
218#endif
219
220 // class error_category ------------------------------------------------//
221
222 class error_category : public noncopyable
223 {
224#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
225
226 private:
227
228 class std_category: public std::error_category
229 {
230 private:
231
232 boost::system::error_category const * pc_;
233
234 public:
235
236 explicit std_category( boost::system::error_category const * pc ): pc_( pc )
237 {
238 }
239
240 virtual const char * name() const BOOST_NOEXCEPT
241 {
242 return pc_->name();
243 }
244
245 virtual std::string message( int ev ) const
246 {
247 return pc_->message( ev );
248 }
249
250 virtual std::error_condition default_error_condition( int ev ) const
251 BOOST_NOEXCEPT;
252 virtual bool equivalent( int code, const std::error_condition & condition ) const
253 BOOST_NOEXCEPT;
254 virtual bool equivalent( const std::error_code & code, int condition ) const
255 BOOST_NOEXCEPT;
256 };
257
258 std_category std_cat_;
259
260 public:
261
262 error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {}
263
264 operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT
265 {
266 // do not map generic to std::generic on purpose; occasionally,
267 // there are two std::generic categories in a program, which leads
268 // to error codes/conditions mysteriously not being equal to themselves
269 return std_cat_;
270 }
271
272#else
273
274 // to maintain ABI compatibility between 03 and 11,
275 // define a class with the same layout
276
277 private:
278
279 class std_category
280 {
281 private:
282
283 boost::system::error_category const * pc_;
284
285 public:
286
287 explicit std_category( boost::system::error_category const * pc ): pc_( pc )
288 {
289 }
290
291 virtual ~std_category() {}
292
293 virtual const char * name() const BOOST_NOEXCEPT
294 {
295 return pc_->name();
296 }
297
298 // we can't define message, because (1) it returns an std::string,
299 // which can be different between 03 and 11, and (2) on mingw, there
300 // are actually two `message` functions, not one, so it doesn't work
301 // even if we do
302
303 // neither can we define default_error_condition or equivalent
304
305 // if these functions are called, it will crash, but that's still
306 // better than the alternative of having the class layout change
307 };
308
309 std_category std_cat_;
310
311 public:
312
313 error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {}
314
315#endif
316
317 public:
318 virtual ~error_category(){}
319
320 virtual const char * name() const BOOST_SYSTEM_NOEXCEPT = 0;
321 virtual std::string message( int ev ) const = 0;
322 inline virtual error_condition default_error_condition( int ev ) const
323 BOOST_SYSTEM_NOEXCEPT;
324 inline virtual bool equivalent( int code,
325 const error_condition & condition ) const
326 BOOST_SYSTEM_NOEXCEPT;
327 inline virtual bool equivalent( const error_code & code,
328 int condition ) const BOOST_SYSTEM_NOEXCEPT;
329
330 bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT
331 { return this == &rhs; }
332 bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT
333 { return this != &rhs; }
334 bool operator<( const error_category & rhs ) const BOOST_SYSTEM_NOEXCEPT
335 { return std::less<const error_category*>()( this, &rhs ); }
336 };
337
338#ifdef BOOST_MSVC
339#pragma warning(pop)
340#endif
341
342 // class error_condition ---------------------------------------------------------//
343
344 // error_conditions are portable, error_codes are system or library specific
345
346 class error_condition
347 {
348 public:
349
350 // constructors:
351 error_condition() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&generic_category()) {}
352 error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
353 : m_val(val), m_cat(&cat) {}
354
355 template <class ErrorConditionEnum>
356 error_condition(ErrorConditionEnum e,
357 typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type*
358 = 0) BOOST_SYSTEM_NOEXCEPT
359 {
360 *this = make_error_condition(e);
361 }
362
363 // modifiers:
364
365 void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
366 {
367 m_val = val;
368 m_cat = &cat;
369 }
370
371 template<typename ErrorConditionEnum>
372 typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum>,
373 error_condition>::type &
374 operator=( ErrorConditionEnum val ) BOOST_SYSTEM_NOEXCEPT
375 {
376 *this = make_error_condition(val);
377 return *this;
378 }
379
380 void clear() BOOST_SYSTEM_NOEXCEPT
381 {
382 m_val = 0;
383 m_cat = &generic_category();
384 }
385
386 // observers:
387 int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; }
388 const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; }
389 std::string message() const { return m_cat->message(value()); }
390
391#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
392
393 explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error
394 {
395 return m_val != 0;
396 }
397
398#else
399
400 typedef void (*unspecified_bool_type)();
401 static void unspecified_bool_true() {}
402
403 operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error
404 {
405 return m_val == 0 ? 0 : unspecified_bool_true;
406 }
407
408 bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error
409 {
410 return m_val == 0;
411 }
412
413#endif
414
415 // relationals:
416 // the more symmetrical non-member syntax allows enum
417 // conversions work for both rhs and lhs.
418 inline friend bool operator==( const error_condition & lhs,
419 const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
420 {
421 return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
422 }
423
424 inline friend bool operator<( const error_condition & lhs,
425 const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
426 // the more symmetrical non-member syntax allows enum
427 // conversions work for both rhs and lhs.
428 {
429 return lhs.m_cat < rhs.m_cat
430 || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
431 }
432
433#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
434
435 operator std::error_condition () const BOOST_SYSTEM_NOEXCEPT
436 {
437 return std::error_condition( value(), category() );
438 }
439
440#endif
441
442 private:
443 int m_val;
444 const error_category * m_cat;
445
446 };
447
448 // class error_code --------------------------------------------------------------//
449
450 // We want error_code to be a value type that can be copied without slicing
451 // and without requiring heap allocation, but we also want it to have
452 // polymorphic behavior based on the error category. This is achieved by
453 // abstract base class error_category supplying the polymorphic behavior,
454 // and error_code containing a pointer to an object of a type derived
455 // from error_category.
456 class error_code
457 {
458 public:
459
460 // constructors:
461 error_code() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&system_category()) {}
462 error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
463 : m_val(val), m_cat(&cat) {}
464
465 template <class ErrorCodeEnum>
466 error_code(ErrorCodeEnum e,
467 typename boost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0)
468 BOOST_SYSTEM_NOEXCEPT
469 {
470 *this = make_error_code(e);
471 }
472
473 // modifiers:
474 void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
475 {
476 m_val = val;
477 m_cat = &cat;
478 }
479
480 template<typename ErrorCodeEnum>
481 typename boost::enable_if<is_error_code_enum<ErrorCodeEnum>, error_code>::type &
482 operator=( ErrorCodeEnum val ) BOOST_SYSTEM_NOEXCEPT
483 {
484 *this = make_error_code(val);
485 return *this;
486 }
487
488 void clear() BOOST_SYSTEM_NOEXCEPT
489 {
490 m_val = 0;
491 m_cat = &system_category();
492 }
493
494 // observers:
495 int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; }
496 const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; }
497 error_condition default_error_condition() const BOOST_SYSTEM_NOEXCEPT
498 { return m_cat->default_error_condition(value()); }
499 std::string message() const { return m_cat->message(value()); }
500
501#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
502
503 explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error
504 {
505 return m_val != 0;
506 }
507
508#else
509
510 typedef void (*unspecified_bool_type)();
511 static void unspecified_bool_true() {}
512
513 operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error
514 {
515 return m_val == 0 ? 0 : unspecified_bool_true;
516 }
517
518 bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error
519 {
520 return m_val == 0;
521 }
522
523#endif
524
525 // relationals:
526 inline friend bool operator==( const error_code & lhs,
527 const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
528 // the more symmetrical non-member syntax allows enum
529 // conversions work for both rhs and lhs.
530 {
531 return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
532 }
533
534 inline friend bool operator<( const error_code & lhs,
535 const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
536 // the more symmetrical non-member syntax allows enum
537 // conversions work for both rhs and lhs.
538 {
539 return lhs.m_cat < rhs.m_cat
540 || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
541 }
542
543#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
544
545 operator std::error_code () const BOOST_SYSTEM_NOEXCEPT
546 {
547 return std::error_code( value(), category() );
548 }
549
550#endif
551
552 private:
553 int m_val;
554 const error_category * m_cat;
555
556 };
557
558 // predefined error_code object used as "throw on error" tag
559# ifdef BOOST_SYSTEM_ENABLE_DEPRECATED
560 BOOST_SYSTEM_DECL extern error_code throws;
561# endif
562
563 // Moving from a "throws" object to a "throws" function without breaking
564 // existing code is a bit of a problem. The workaround is to place the
565 // "throws" function in namespace boost rather than namespace boost::system.
566
567 } // namespace system
568
569 namespace detail
570 {
571 // Misuse of the error_code object is turned into a noisy failure by
572 // poisoning the reference. This particular implementation doesn't
573 // produce warnings or errors from popular compilers, is very efficient
574 // (as determined by inspecting generated code), and does not suffer
575 // from order of initialization problems. In practice, it also seems
576 // cause user function error handling implementation errors to be detected
577 // very early in the development cycle.
578 inline system::error_code* throws()
579 {
580 // See github.com/boostorg/system/pull/12 by visigoth for why the return
581 // is poisoned with nonzero rather than (0). A test, test_throws_usage(),
582 // has been added to error_code_test.cpp, and as visigoth mentioned it
583 // fails on clang for release builds with a return of 0 but works fine
584 // with (1).
585 // Since the undefined behavior sanitizer (-fsanitize=undefined) does not
586 // allow a reference to be formed to the unaligned address of (1), we use
587 // (8) instead.
588 return reinterpret_cast<system::error_code*>(8);
589 }
590 }
591
592 inline system::error_code& throws()
593 { return *detail::throws(); }
594
595 namespace system
596 {
597 // non-member functions ------------------------------------------------//
598
599 inline bool operator!=( const error_code & lhs,
600 const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
601 {
602 return !(lhs == rhs);
603 }
604
605 inline bool operator!=( const error_condition & lhs,
606 const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
607 {
608 return !(lhs == rhs);
609 }
610
611 inline bool operator==( const error_code & code,
612 const error_condition & condition ) BOOST_SYSTEM_NOEXCEPT
613 {
614 return code.category().equivalent( code.value(), condition )
615 || condition.category().equivalent( code, condition.value() );
616 }
617
618 inline bool operator!=( const error_code & lhs,
619 const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT
620 {
621 return !(lhs == rhs);
622 }
623
624 inline bool operator==( const error_condition & condition,
625 const error_code & code ) BOOST_SYSTEM_NOEXCEPT
626 {
627 return condition.category().equivalent( code, condition.value() )
628 || code.category().equivalent( code.value(), condition );
629 }
630
631 inline bool operator!=( const error_condition & lhs,
632 const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT
633 {
634 return !(lhs == rhs);
635 }
636
637 // TODO: both of these may move elsewhere, but the LWG hasn't spoken yet.
638
639 template <class charT, class traits>
640 inline std::basic_ostream<charT,traits>&
641 operator<< (std::basic_ostream<charT,traits>& os, error_code ec)
642 {
643 os << ec.category().name() << ':' << ec.value();
644 return os;
645 }
646
647 inline std::size_t hash_value( const error_code & ec )
648 {
649 return static_cast<std::size_t>(ec.value())
650 + reinterpret_cast<std::size_t>(&ec.category());
651 }
652
653 // make_* functions for errc::errc_t ---------------------------------------------//
654
655 namespace errc
656 {
657 // explicit conversion:
658 inline error_code make_error_code( errc_t e ) BOOST_SYSTEM_NOEXCEPT
659 { return error_code( e, generic_category() ); }
660
661 // implicit conversion:
662 inline error_condition make_error_condition( errc_t e ) BOOST_SYSTEM_NOEXCEPT
663 { return error_condition( e, generic_category() ); }
664 }
665
666 // error_category default implementation -----------------------------------------//
667
668 error_condition error_category::default_error_condition( int ev ) const
669 BOOST_SYSTEM_NOEXCEPT
670 {
671 return error_condition( ev, *this );
672 }
673
674 bool error_category::equivalent( int code,
675 const error_condition & condition ) const BOOST_SYSTEM_NOEXCEPT
676 {
677 return default_error_condition( code ) == condition;
678 }
679
680 bool error_category::equivalent( const error_code & code,
681 int condition ) const BOOST_SYSTEM_NOEXCEPT
682 {
683 return *this == code.category() && code.value() == condition;
684 }
685
686#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
687
688 inline std::error_condition error_category::std_category::default_error_condition(
689 int ev ) const BOOST_NOEXCEPT
690 {
691 return pc_->default_error_condition( ev );
692 }
693
694 inline bool error_category::std_category::equivalent( int code,
695 const std::error_condition & condition ) const BOOST_NOEXCEPT
696 {
697 if( condition.category() == *this )
698 {
699 boost::system::error_condition bn( condition.value(), *pc_ );
700 return pc_->equivalent( code, bn );
701 }
702 else if( condition.category() == std::generic_category()
703 || condition.category() == boost::system::generic_category() )
704 {
705 boost::system::error_condition bn( condition.value(),
706 boost::system::generic_category() );
707
708 return pc_->equivalent( code, bn );
709 }
710#ifndef BOOST_NO_RTTI
711 else if( std_category const* pc2 = dynamic_cast< std_category const* >(
712 &condition.category() ) )
713 {
714 boost::system::error_condition bn( condition.value(), *pc2->pc_ );
715 return pc_->equivalent( code, bn );
716 }
717#endif
718 else
719 {
720 return default_error_condition( code ) == condition;
721 }
722 }
723
724 inline bool error_category::std_category::equivalent( const std::error_code & code,
725 int condition ) const BOOST_NOEXCEPT
726 {
727 if( code.category() == *this )
728 {
729 boost::system::error_code bc( code.value(), *pc_ );
730 return pc_->equivalent( bc, condition );
731 }
732 else if( code.category() == std::generic_category()
733 || code.category() == boost::system::generic_category() )
734 {
735 boost::system::error_code bc( code.value(),
736 boost::system::generic_category() );
737
738 return pc_->equivalent( bc, condition );
739 }
740#ifndef BOOST_NO_RTTI
741 else if( std_category const* pc2 = dynamic_cast< std_category const* >(
742 &code.category() ) )
743 {
744 boost::system::error_code bc( code.value(), *pc2->pc_ );
745 return pc_->equivalent( bc, condition );
746 }
747#endif
748 else if( *pc_ == boost::system::generic_category() )
749 {
750 return std::generic_category().equivalent( code, condition );
751 }
752 else
753 {
754 return false;
755 }
756 }
757
758#endif
759
760 } // namespace system
761} // namespace boost
762
763#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
764
765# ifdef BOOST_ERROR_CODE_HEADER_ONLY
766# include <boost/system/detail/error_code.ipp>
767# endif
768
769#endif // BOOST_SYSTEM_ERROR_CODE_HPP
770