-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy patherror_code.cpp
More file actions
113 lines (99 loc) · 3.62 KB
/
error_code.cpp
File metadata and controls
113 lines (99 loc) · 3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// std::error_code: a typed (value, category) pair for recoverable errors.
// Companion file: error_handling.cpp covers the C-style errno side.
#include <cerrno>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <system_error>
// 2.1 Reporting an error via an out parameter.
void open_file(const std::string& path, std::error_code& ec) {
std::ifstream file(path);
if (!file) {
ec = std::make_error_code(std::errc::no_such_file_or_directory);
return;
}
ec.clear();
}
// 2.2 Wrapping an errno into an error_code.
void remove_file(const std::string& path, std::error_code& ec) {
if (std::remove(path.c_str()) != 0)
ec = std::error_code(errno, std::system_category());
else
ec.clear();
}
// 2.5 A custom error category.
enum class parse_err { ok = 0, empty_input, bad_number, out_of_range };
class parse_category_t : public std::error_category {
public:
const char* name() const noexcept override { return "parse"; }
std::string message(int v) const override {
switch (static_cast<parse_err>(v)) {
case parse_err::empty_input: return "empty input";
case parse_err::bad_number: return "not a number";
case parse_err::out_of_range: return "value out of range";
default: return "ok";
}
}
};
const std::error_category& parse_category() {
static parse_category_t c;
return c;
}
std::error_code make_error_code(parse_err e) {
return {static_cast<int>(e), parse_category()};
}
namespace std {
template <>
struct is_error_code_enum<parse_err> : true_type {};
} // namespace std
int main() {
// ---- 2.1 out-parameter style ----
std::cout << "--- out-parameter error_code ---\n";
std::error_code ec;
open_file("nope.txt", ec);
if (ec) {
std::cout << "open failed: " << ec.message()
<< " (value " << ec.value()
<< ", category " << ec.category().name() << ")\n";
}
// ---- 2.2 wrapping errno ----
std::cout << "--- wrap errno into error_code ---\n";
remove_file("nope.txt", ec);
if (ec) {
std::cout << "remove failed: " << ec.message()
<< " (value " << ec.value() << ")\n";
}
// ---- 2.3 std::filesystem non-throwing overload ----
std::cout << "--- filesystem non-throwing API ---\n";
auto sz = std::filesystem::file_size("nope.txt", ec);
if (ec) {
std::cout << "file_size failed: " << ec.message() << "\n";
} else {
std::cout << "size = " << sz << "\n";
}
// ---- 2.4 comparing against a portable std::errc condition ----
std::cout << "--- compare against std::errc ---\n";
if (ec == std::errc::no_such_file_or_directory) {
std::cout << "matched std::errc::no_such_file_or_directory\n";
}
// ---- 2.5 custom category ----
std::cout << "--- custom parse_category ---\n";
std::error_code pec = make_error_code(parse_err::bad_number);
std::cout << "category: " << pec.category().name()
<< ", value: " << pec.value()
<< ", message: " << pec.message() << "\n";
if (pec == parse_err::bad_number) {
std::cout << "matched parse_err::bad_number\n";
}
// ---- 4. throwing form: std::system_error wraps an error_code ----
std::cout << "--- std::system_error wraps error_code ---\n";
try {
throw std::system_error(
std::error_code(EACCES, std::system_category()),
"demo");
} catch (const std::system_error& e) {
std::cout << "caught: " << e.what()
<< " (code " << e.code().value() << ")\n";
}
}