Skip to content

Commit e4466c2

Browse files
committed
Implement the useful parts of std::error_code.
I'm omitting `std::error_condition` because I don't believe it's useful, although I admit its metaprogramming would be fun. The `error_code::to_string()` method is not standard, but it has the same behavior as the standard `operator<<(ostream&, const error_code&)`.
1 parent f8cffb7 commit e4466c2

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
3+
#include "scratch/bits/containers/string.h"
4+
#include "scratch/bits/error-code/error-code.h"
5+
6+
namespace scratch::detail {
7+
8+
struct system_category : error_category {
9+
const char *name() const noexcept override { return "system"; }
10+
11+
string message(int value) const override {
12+
switch (value) {
13+
case 0: return "success";
14+
}
15+
__builtin_unreachable();
16+
}
17+
};
18+
19+
} // namespace scratch::detail
20+
21+
namespace scratch {
22+
23+
const error_category& system_category() noexcept
24+
{
25+
static detail::system_category instance;
26+
return instance;
27+
}
28+
29+
} // namespace scratch

include/scratch/system_error

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
#pragma once
2+
3+
#include "bits/error-code/error-code.h"
4+
#include "bits/error-code/system-category.h"

0 commit comments

Comments
 (0)