|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include "scratch/bits/containers/string.h" |
| 4 | +#include "scratch/bits/functional/less.h" |
| 5 | +#include "scratch/bits/type-traits/integral-constant.h" |
| 6 | + |
| 7 | +namespace scratch { |
| 8 | + |
| 9 | +template<class E> struct is_error_code_enum : false_type {}; |
| 10 | + |
| 11 | +class error_category { |
| 12 | +public: |
| 13 | + constexpr error_category() noexcept = default; |
| 14 | + error_category(const error_category&) = delete; |
| 15 | + |
| 16 | + virtual const char *name() const noexcept = 0; |
| 17 | + virtual string message(int value) const = 0; |
| 18 | + virtual ~error_category() = default; |
| 19 | + |
| 20 | + bool operator==(const error_category& rhs) const noexcept { return this == &rhs; } |
| 21 | + bool operator!=(const error_category& rhs) const noexcept { return this != &rhs; } |
| 22 | + bool operator<(const error_category& rhs) const noexcept { return less<>()(this, &rhs); } |
| 23 | + bool operator<=(const error_category& rhs) const noexcept { return less_equal<>()(this, &rhs); } |
| 24 | + bool operator>(const error_category& rhs) const noexcept { return greater<>()(this, &rhs); } |
| 25 | + bool operator>=(const error_category& rhs) const noexcept { return greater_equal<>()(this, &rhs); } |
| 26 | +}; |
| 27 | + |
| 28 | +const error_category& system_category() noexcept; // forward declaration |
| 29 | + |
| 30 | +class error_code { |
| 31 | + int m_value; |
| 32 | + const error_category *m_category; |
| 33 | +public: |
| 34 | + int value() const noexcept { return m_value; } |
| 35 | + const error_category& category() const noexcept { return *m_category; } |
| 36 | + |
| 37 | + error_code() noexcept : error_code(0, system_category()) {} |
| 38 | + error_code(int v, const error_category& cat) noexcept : m_value(v), m_category(&cat) {} |
| 39 | + |
| 40 | + template<class E, class = enable_if_t<is_error_code_enum<E>::value>> |
| 41 | + error_code(E v) { |
| 42 | + *this = make_error_code(v); |
| 43 | + } |
| 44 | + |
| 45 | + explicit operator bool() const noexcept { return m_value; } |
| 46 | + |
| 47 | + void clear() noexcept { *this = error_code(0, system_category()); } |
| 48 | + |
| 49 | + string message() const { return m_category->message(m_value); } |
| 50 | + string to_string() const { return m_category->name() + (":" + message()); } |
| 51 | +}; |
| 52 | + |
| 53 | +// The standard provides only operators == != <; the other three are non-standard. |
| 54 | +inline bool operator==(const error_code& a, const error_code& b) noexcept { return a.category() == b.category() && a.value() == b.value(); } |
| 55 | +inline bool operator!=(const error_code& a, const error_code& b) noexcept { return !(a == b); } |
| 56 | +inline bool operator< (const error_code& a, const error_code& b) noexcept { return a.category() < b.category() || (a.category() == b.category() && a.value() < b.value()); } |
| 57 | +inline bool operator<=(const error_code& a, const error_code& b) noexcept { return !(b < a); } |
| 58 | +inline bool operator> (const error_code& a, const error_code& b) noexcept { return (b < a); } |
| 59 | +inline bool operator>=(const error_code& a, const error_code& b) noexcept { return !(a < b); } |
| 60 | + |
| 61 | +} // namespace scratch |
0 commit comments