| 1 | /* Proposed SG14 status_code |
| 2 | (C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits) |
| 3 | File Created: Feb 2018 |
| 4 | |
| 5 | |
| 6 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | you may not use this file except in compliance with the License. |
| 8 | You may obtain a copy of the License in the accompanying file |
| 9 | Licence.txt or at |
| 10 | |
| 11 | http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | |
| 13 | Unless required by applicable law or agreed to in writing, software |
| 14 | distributed under the License is distributed on an "AS IS" BASIS, |
| 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 16 | See the License for the specific language governing permissions and |
| 17 | limitations under the License. |
| 18 | |
| 19 | |
| 20 | Distributed under the Boost Software License, Version 1.0. |
| 21 | (See accompanying file Licence.txt or copy at |
| 22 | http://www.boost.org/LICENSE_1_0.txt) |
| 23 | */ |
| 24 | |
| 25 | #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP |
| 26 | #define BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP |
| 27 | |
| 28 | #include "status_error.hpp" |
| 29 | |
| 30 | #include <cerrno> // for error constants |
| 31 | |
| 32 | BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN |
| 33 | |
| 34 | //! The generic error coding (POSIX) |
| 35 | enum class errc : int |
| 36 | { |
| 37 | success = 0, |
| 38 | unknown = -1, |
| 39 | |
| 40 | address_family_not_supported = EAFNOSUPPORT, |
| 41 | address_in_use = EADDRINUSE, |
| 42 | address_not_available = EADDRNOTAVAIL, |
| 43 | already_connected = EISCONN, |
| 44 | argument_list_too_long = E2BIG, |
| 45 | argument_out_of_domain = EDOM, |
| 46 | bad_address = EFAULT, |
| 47 | bad_file_descriptor = EBADF, |
| 48 | bad_message = EBADMSG, |
| 49 | broken_pipe = EPIPE, |
| 50 | connection_aborted = ECONNABORTED, |
| 51 | connection_already_in_progress = EALREADY, |
| 52 | connection_refused = ECONNREFUSED, |
| 53 | connection_reset = ECONNRESET, |
| 54 | cross_device_link = EXDEV, |
| 55 | destination_address_required = EDESTADDRREQ, |
| 56 | device_or_resource_busy = EBUSY, |
| 57 | directory_not_empty = ENOTEMPTY, |
| 58 | executable_format_error = ENOEXEC, |
| 59 | file_exists = EEXIST, |
| 60 | file_too_large = EFBIG, |
| 61 | filename_too_long = ENAMETOOLONG, |
| 62 | function_not_supported = ENOSYS, |
| 63 | host_unreachable = EHOSTUNREACH, |
| 64 | identifier_removed = EIDRM, |
| 65 | illegal_byte_sequence = EILSEQ, |
| 66 | inappropriate_io_control_operation = ENOTTY, |
| 67 | interrupted = EINTR, |
| 68 | invalid_argument = EINVAL, |
| 69 | invalid_seek = ESPIPE, |
| 70 | io_error = EIO, |
| 71 | is_a_directory = EISDIR, |
| 72 | message_size = EMSGSIZE, |
| 73 | network_down = ENETDOWN, |
| 74 | network_reset = ENETRESET, |
| 75 | network_unreachable = ENETUNREACH, |
| 76 | no_buffer_space = ENOBUFS, |
| 77 | no_child_process = ECHILD, |
| 78 | no_link = ENOLINK, |
| 79 | no_lock_available = ENOLCK, |
| 80 | no_message = ENOMSG, |
| 81 | no_protocol_option = ENOPROTOOPT, |
| 82 | no_space_on_device = ENOSPC, |
| 83 | no_stream_resources = ENOSR, |
| 84 | no_such_device_or_address = ENXIO, |
| 85 | no_such_device = ENODEV, |
| 86 | no_such_file_or_directory = ENOENT, |
| 87 | no_such_process = ESRCH, |
| 88 | not_a_directory = ENOTDIR, |
| 89 | not_a_socket = ENOTSOCK, |
| 90 | not_a_stream = ENOSTR, |
| 91 | not_connected = ENOTCONN, |
| 92 | not_enough_memory = ENOMEM, |
| 93 | not_supported = ENOTSUP, |
| 94 | operation_canceled = ECANCELED, |
| 95 | operation_in_progress = EINPROGRESS, |
| 96 | operation_not_permitted = EPERM, |
| 97 | operation_not_supported = EOPNOTSUPP, |
| 98 | operation_would_block = EWOULDBLOCK, |
| 99 | owner_dead = EOWNERDEAD, |
| 100 | permission_denied = EACCES, |
| 101 | protocol_error = EPROTO, |
| 102 | protocol_not_supported = EPROTONOSUPPORT, |
| 103 | read_only_file_system = EROFS, |
| 104 | resource_deadlock_would_occur = EDEADLK, |
| 105 | resource_unavailable_try_again = EAGAIN, |
| 106 | result_out_of_range = ERANGE, |
| 107 | state_not_recoverable = ENOTRECOVERABLE, |
| 108 | stream_timeout = ETIME, |
| 109 | text_file_busy = ETXTBSY, |
| 110 | timed_out = ETIMEDOUT, |
| 111 | too_many_files_open_in_system = ENFILE, |
| 112 | too_many_files_open = EMFILE, |
| 113 | too_many_links = EMLINK, |
| 114 | too_many_symbolic_link_levels = ELOOP, |
| 115 | value_too_large = EOVERFLOW, |
| 116 | wrong_protocol_type = EPROTOTYPE |
| 117 | }; |
| 118 | |
| 119 | namespace detail |
| 120 | { |
| 121 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline const char *generic_code_message(errc code) noexcept |
| 122 | { |
| 123 | switch(code) |
| 124 | { |
| 125 | case errc::success: |
| 126 | return "Success" ; |
| 127 | case errc::address_family_not_supported: |
| 128 | return "Address family not supported by protocol" ; |
| 129 | case errc::address_in_use: |
| 130 | return "Address already in use" ; |
| 131 | case errc::address_not_available: |
| 132 | return "Cannot assign requested address" ; |
| 133 | case errc::already_connected: |
| 134 | return "Transport endpoint is already connected" ; |
| 135 | case errc::argument_list_too_long: |
| 136 | return "Argument list too long" ; |
| 137 | case errc::argument_out_of_domain: |
| 138 | return "Numerical argument out of domain" ; |
| 139 | case errc::bad_address: |
| 140 | return "Bad address" ; |
| 141 | case errc::bad_file_descriptor: |
| 142 | return "Bad file descriptor" ; |
| 143 | case errc::bad_message: |
| 144 | return "Bad message" ; |
| 145 | case errc::broken_pipe: |
| 146 | return "Broken pipe" ; |
| 147 | case errc::connection_aborted: |
| 148 | return "Software caused connection abort" ; |
| 149 | case errc::connection_already_in_progress: |
| 150 | return "Operation already in progress" ; |
| 151 | case errc::connection_refused: |
| 152 | return "Connection refused" ; |
| 153 | case errc::connection_reset: |
| 154 | return "Connection reset by peer" ; |
| 155 | case errc::cross_device_link: |
| 156 | return "Invalid cross-device link" ; |
| 157 | case errc::destination_address_required: |
| 158 | return "Destination address required" ; |
| 159 | case errc::device_or_resource_busy: |
| 160 | return "Device or resource busy" ; |
| 161 | case errc::directory_not_empty: |
| 162 | return "Directory not empty" ; |
| 163 | case errc::executable_format_error: |
| 164 | return "Exec format error" ; |
| 165 | case errc::file_exists: |
| 166 | return "File exists" ; |
| 167 | case errc::file_too_large: |
| 168 | return "File too large" ; |
| 169 | case errc::filename_too_long: |
| 170 | return "File name too long" ; |
| 171 | case errc::function_not_supported: |
| 172 | return "Function not implemented" ; |
| 173 | case errc::host_unreachable: |
| 174 | return "No route to host" ; |
| 175 | case errc::identifier_removed: |
| 176 | return "Identifier removed" ; |
| 177 | case errc::illegal_byte_sequence: |
| 178 | return "Invalid or incomplete multibyte or wide character" ; |
| 179 | case errc::inappropriate_io_control_operation: |
| 180 | return "Inappropriate ioctl for device" ; |
| 181 | case errc::interrupted: |
| 182 | return "Interrupted system call" ; |
| 183 | case errc::invalid_argument: |
| 184 | return "Invalid argument" ; |
| 185 | case errc::invalid_seek: |
| 186 | return "Illegal seek" ; |
| 187 | case errc::io_error: |
| 188 | return "Input/output error" ; |
| 189 | case errc::is_a_directory: |
| 190 | return "Is a directory" ; |
| 191 | case errc::message_size: |
| 192 | return "Message too long" ; |
| 193 | case errc::network_down: |
| 194 | return "Network is down" ; |
| 195 | case errc::network_reset: |
| 196 | return "Network dropped connection on reset" ; |
| 197 | case errc::network_unreachable: |
| 198 | return "Network is unreachable" ; |
| 199 | case errc::no_buffer_space: |
| 200 | return "No buffer space available" ; |
| 201 | case errc::no_child_process: |
| 202 | return "No child processes" ; |
| 203 | case errc::no_link: |
| 204 | return "Link has been severed" ; |
| 205 | case errc::no_lock_available: |
| 206 | return "No locks available" ; |
| 207 | case errc::no_message: |
| 208 | return "No message of desired type" ; |
| 209 | case errc::no_protocol_option: |
| 210 | return "Protocol not available" ; |
| 211 | case errc::no_space_on_device: |
| 212 | return "No space left on device" ; |
| 213 | case errc::no_stream_resources: |
| 214 | return "Out of streams resources" ; |
| 215 | case errc::no_such_device_or_address: |
| 216 | return "No such device or address" ; |
| 217 | case errc::no_such_device: |
| 218 | return "No such device" ; |
| 219 | case errc::no_such_file_or_directory: |
| 220 | return "No such file or directory" ; |
| 221 | case errc::no_such_process: |
| 222 | return "No such process" ; |
| 223 | case errc::not_a_directory: |
| 224 | return "Not a directory" ; |
| 225 | case errc::not_a_socket: |
| 226 | return "Socket operation on non-socket" ; |
| 227 | case errc::not_a_stream: |
| 228 | return "Device not a stream" ; |
| 229 | case errc::not_connected: |
| 230 | return "Transport endpoint is not connected" ; |
| 231 | case errc::not_enough_memory: |
| 232 | return "Cannot allocate memory" ; |
| 233 | #if ENOTSUP != EOPNOTSUPP |
| 234 | case errc::not_supported: |
| 235 | return "Operation not supported" ; |
| 236 | #endif |
| 237 | case errc::operation_canceled: |
| 238 | return "Operation canceled" ; |
| 239 | case errc::operation_in_progress: |
| 240 | return "Operation now in progress" ; |
| 241 | case errc::operation_not_permitted: |
| 242 | return "Operation not permitted" ; |
| 243 | case errc::operation_not_supported: |
| 244 | return "Operation not supported" ; |
| 245 | #if EAGAIN != EWOULDBLOCK |
| 246 | case errc::operation_would_block: |
| 247 | return "Resource temporarily unavailable" ; |
| 248 | #endif |
| 249 | case errc::owner_dead: |
| 250 | return "Owner died" ; |
| 251 | case errc::permission_denied: |
| 252 | return "Permission denied" ; |
| 253 | case errc::protocol_error: |
| 254 | return "Protocol error" ; |
| 255 | case errc::protocol_not_supported: |
| 256 | return "Protocol not supported" ; |
| 257 | case errc::read_only_file_system: |
| 258 | return "Read-only file system" ; |
| 259 | case errc::resource_deadlock_would_occur: |
| 260 | return "Resource deadlock avoided" ; |
| 261 | case errc::resource_unavailable_try_again: |
| 262 | return "Resource temporarily unavailable" ; |
| 263 | case errc::result_out_of_range: |
| 264 | return "Numerical result out of range" ; |
| 265 | case errc::state_not_recoverable: |
| 266 | return "State not recoverable" ; |
| 267 | case errc::stream_timeout: |
| 268 | return "Timer expired" ; |
| 269 | case errc::text_file_busy: |
| 270 | return "Text file busy" ; |
| 271 | case errc::timed_out: |
| 272 | return "Connection timed out" ; |
| 273 | case errc::too_many_files_open_in_system: |
| 274 | return "Too many open files in system" ; |
| 275 | case errc::too_many_files_open: |
| 276 | return "Too many open files" ; |
| 277 | case errc::too_many_links: |
| 278 | return "Too many links" ; |
| 279 | case errc::too_many_symbolic_link_levels: |
| 280 | return "Too many levels of symbolic links" ; |
| 281 | case errc::value_too_large: |
| 282 | return "Value too large for defined data type" ; |
| 283 | case errc::wrong_protocol_type: |
| 284 | return "Protocol wrong type for socket" ; |
| 285 | default: |
| 286 | return "unknown" ; |
| 287 | } |
| 288 | } |
| 289 | } // namespace detail |
| 290 | |
| 291 | /*! The implementation of the domain for generic status codes, those mapped by `errc` (POSIX). |
| 292 | */ |
| 293 | class _generic_code_domain : public status_code_domain |
| 294 | { |
| 295 | template <class> friend class status_code; |
| 296 | using _base = status_code_domain; |
| 297 | |
| 298 | public: |
| 299 | //! The value type of the generic code, which is an `errc` as per POSIX. |
| 300 | using value_type = errc; |
| 301 | using string_ref = _base::string_ref; |
| 302 | |
| 303 | public: |
| 304 | //! Default constructor |
| 305 | constexpr explicit _generic_code_domain(typename _base::unique_id_type id = 0x746d6354f4f733e9) noexcept |
| 306 | : _base(id) |
| 307 | { |
| 308 | } |
| 309 | _generic_code_domain(const _generic_code_domain &) = default; |
| 310 | _generic_code_domain(_generic_code_domain &&) = default; |
| 311 | _generic_code_domain &operator=(const _generic_code_domain &) = default; |
| 312 | _generic_code_domain &operator=(_generic_code_domain &&) = default; |
| 313 | ~_generic_code_domain() = default; |
| 314 | |
| 315 | //! Constexpr singleton getter. Returns the constexpr generic_code_domain variable. |
| 316 | static inline constexpr const _generic_code_domain &get(); |
| 317 | |
| 318 | virtual _base::string_ref name() const noexcept override { return string_ref("generic domain" ); } // NOLINT |
| 319 | |
| 320 | virtual payload_info_t payload_info() const noexcept override |
| 321 | { |
| 322 | return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type), |
| 323 | (alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)}; |
| 324 | } |
| 325 | |
| 326 | protected: |
| 327 | virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT |
| 328 | { |
| 329 | assert(code.domain() == *this); // NOLINT |
| 330 | return static_cast<const generic_code &>(code).value() != errc::success; // NOLINT |
| 331 | } |
| 332 | virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT |
| 333 | { |
| 334 | assert(code1.domain() == *this); // NOLINT |
| 335 | const auto &c1 = static_cast<const generic_code &>(code1); // NOLINT |
| 336 | if(code2.domain() == *this) |
| 337 | { |
| 338 | const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT |
| 339 | return c1.value() == c2.value(); |
| 340 | } |
| 341 | return false; |
| 342 | } |
| 343 | virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT |
| 344 | { |
| 345 | assert(code.domain() == *this); // NOLINT |
| 346 | return static_cast<const generic_code &>(code); // NOLINT |
| 347 | } |
| 348 | virtual _base::string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT |
| 349 | { |
| 350 | assert(code.domain() == *this); // NOLINT |
| 351 | const auto &c = static_cast<const generic_code &>(code); // NOLINT |
| 352 | return string_ref(detail::generic_code_message(code: c.value())); |
| 353 | } |
| 354 | #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) |
| 355 | BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT |
| 356 | { |
| 357 | assert(code.domain() == *this); // NOLINT |
| 358 | const auto &c = static_cast<const generic_code &>(code); // NOLINT |
| 359 | throw status_error<_generic_code_domain>(c); |
| 360 | } |
| 361 | #endif |
| 362 | }; |
| 363 | //! A specialisation of `status_error` for the generic code domain. |
| 364 | using generic_error = status_error<_generic_code_domain>; |
| 365 | //! A constexpr source variable for the generic code domain, which is that of `errc` (POSIX). Returned by `_generic_code_domain::get()`. |
| 366 | constexpr _generic_code_domain generic_code_domain; |
| 367 | inline constexpr const _generic_code_domain &_generic_code_domain::get() |
| 368 | { |
| 369 | return generic_code_domain; |
| 370 | } |
| 371 | // Enable implicit construction of generic_code from errc |
| 372 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline generic_code make_status_code(errc c) noexcept |
| 373 | { |
| 374 | return generic_code(in_place, c); |
| 375 | } |
| 376 | |
| 377 | |
| 378 | /*************************************************************************************************************/ |
| 379 | |
| 380 | |
| 381 | template <class T> inline BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 bool status_code<void>::equivalent(const status_code<T> &o) const noexcept |
| 382 | { |
| 383 | if(_domain && o._domain) |
| 384 | { |
| 385 | if(_domain->_do_equivalent(code1: *this, code2: o)) |
| 386 | { |
| 387 | return true; |
| 388 | } |
| 389 | if(o._domain->_do_equivalent(o, *this)) |
| 390 | { |
| 391 | return true; |
| 392 | } |
| 393 | generic_code c1 = o._domain->_generic_code(o); |
| 394 | if(c1.value() != errc::unknown && _domain->_do_equivalent(code1: *this, code2: c1)) |
| 395 | { |
| 396 | return true; |
| 397 | } |
| 398 | generic_code c2 = _domain->_generic_code(code: *this); |
| 399 | if(c2.value() != errc::unknown && o._domain->_do_equivalent(o, c2)) |
| 400 | { |
| 401 | return true; |
| 402 | } |
| 403 | } |
| 404 | // If we are both empty, we are equivalent, otherwise not equivalent |
| 405 | return (!_domain && !o._domain); |
| 406 | } |
| 407 | //! True if the status code's are semantically equal via `equivalent()`. |
| 408 | template <class DomainType1, class DomainType2> |
| 409 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept |
| 410 | { |
| 411 | return a.equivalent(b); |
| 412 | } |
| 413 | //! True if the status code's are not semantically equal via `equivalent()`. |
| 414 | template <class DomainType1, class DomainType2> |
| 415 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept |
| 416 | { |
| 417 | return !a.equivalent(b); |
| 418 | } |
| 419 | //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`. |
| 420 | BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, // |
| 421 | class MakeStatusCodeResult = |
| 422 | typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found |
| 423 | BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code |
| 424 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b) |
| 425 | { |
| 426 | return a.equivalent(make_status_code(b)); |
| 427 | } |
| 428 | //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`. |
| 429 | BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, // |
| 430 | class MakeStatusCodeResult = |
| 431 | typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found |
| 432 | BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code |
| 433 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b) |
| 434 | { |
| 435 | return b.equivalent(make_status_code(a)); |
| 436 | } |
| 437 | //! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`. |
| 438 | BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T, // |
| 439 | class MakeStatusCodeResult = |
| 440 | typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found |
| 441 | BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code |
| 442 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b) |
| 443 | { |
| 444 | return !a.equivalent(make_status_code(b)); |
| 445 | } |
| 446 | //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`. |
| 447 | BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1, // |
| 448 | class MakeStatusCodeResult = |
| 449 | typename detail::safe_get_make_status_code_result<const T &>::type) // Safe ADL lookup of make_status_code(), returns void if not found |
| 450 | BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value)) // ADL makes a status code |
| 451 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b) |
| 452 | { |
| 453 | return !b.equivalent(make_status_code(a)); |
| 454 | } |
| 455 | //! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`. |
| 456 | template <class DomainType1, class T, // |
| 457 | class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated |
| 458 | > |
| 459 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b) |
| 460 | { |
| 461 | return a.equivalent(QuickStatusCodeType(b)); |
| 462 | } |
| 463 | //! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`. |
| 464 | template <class T, class DomainType1, // |
| 465 | class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated |
| 466 | > |
| 467 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b) |
| 468 | { |
| 469 | return b.equivalent(QuickStatusCodeType(a)); |
| 470 | } |
| 471 | //! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`. |
| 472 | template <class DomainType1, class T, // |
| 473 | class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated |
| 474 | > |
| 475 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b) |
| 476 | { |
| 477 | return !a.equivalent(QuickStatusCodeType(b)); |
| 478 | } |
| 479 | //! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`. |
| 480 | template <class T, class DomainType1, // |
| 481 | class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated |
| 482 | > |
| 483 | BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b) |
| 484 | { |
| 485 | return !b.equivalent(QuickStatusCodeType(a)); |
| 486 | } |
| 487 | |
| 488 | |
| 489 | BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END |
| 490 | |
| 491 | #endif |
| 492 | |