-
Notifications
You must be signed in to change notification settings - Fork 0
/
example.cpp
122 lines (109 loc) · 3.94 KB
/
example.cpp
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
114
115
116
117
118
119
120
121
122
//
// Created by Youtao Guo on 2023/8/26.
//
#include <cassert>
#include <iostream>
#include "result.hpp"
using result::Result;
template <class T>
Result<T, result::Error> ElementaryArithmeticFromZeroToMillion(char op, T x, T y) {
const T million = 1'000'000;
if (!(x >= 0 && x <= million) || !(y >= 0 && y <= million)) {
return {result::Err{}, result::OutOfRangeError{}};
}
using res_t = Result<T, result::Error>;
T res{};
switch (op) {
case '+':
res = x + y;
return (res >= 0 && res <= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};
case '-':
res = x - y;
return (res >= 0 && res <= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};
case '*':
res = x * y;
return (res >= 0 && res <= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};
case '/':
if (y == 0) {
return {result::Err{}, result::DivideByZeroError{}};
}
res = x / y;
return (res >= 0 && res <= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};
default:
return {result::Err{}, result::InvalidArgumentError{}};
}
}
int invalid_argument_handler(result::InvalidArgumentError) {
std::cout << "invalid argument\n";
return 0;
}
void MoveResult() {
Result<std::string, int> res(result::Ok{}, 100, '0');
std::cout << "res is " << (res.value_or("").empty() ? "empty" : "not empty") << " before moved\n";
auto str = std::move(res).value_or("");
std::cout << "res is " << (res.value_or("").empty() ? "empty" : "not empty") << " after moved\n";
}
int main() {
auto v1 = ElementaryArithmeticFromZeroToMillion('+', 4, 3).match(
result::Ok() = [](int v) { return v; },
result::Err() = [](result::Error&&) { return 0; });
std::cout << v1 << '\n';
auto v2 = ElementaryArithmeticFromZeroToMillion('-', 1.5, 10.5).match(
result::Ok() = [](double v) { return v; },
result::Err() =
[](result::OutOfRangeError) {
std::cout << "the arguments of calculating v2 out of range\n";
return 0;
},
result::Err() =
[](result::RangeError) {
std::cout << "the result of calculating v2 out of range\n";
return 0;
},
result::Err() =
[](result::Error&&) {
std::cout << "unknown error\n";
return 0;
});
auto res = ElementaryArithmeticFromZeroToMillion('^', 1, 0);
res.error().match(
[](result::OutOfRangeError) {
std::cout << "the arguments out of range\n";
return 0;
},
invalid_argument_handler,
[](result::Error) {
std::cout << "unknown error\n";
return 0;
});
res.error().match(
[](result::Error) {
std::cout << "unknown error\n";
return 0;
},
invalid_argument_handler
);
auto v3 = std::move(res)
.or_else([](const result::Error&) {
std::cout << "op ^ failed, change to op /\n";
return ElementaryArithmeticFromZeroToMillion('/', 1, 0);
})
.and_then([](int v) {
std::cout << "op / succeed\n";
return Result<int, result::Error>{v};
})
.or_else([](const result::Error&) {
std::cout << "op / failed, change to op +\n";
return ElementaryArithmeticFromZeroToMillion('+', 1, 0);
})
.and_then([](int v) {
std::cout << "op + succeed, time the result by 10\n";
return ElementaryArithmeticFromZeroToMillion('*', v, 10);
})
.or_else([](const result::Error&) {
std::cout << "eventually failed, set value as -1\n";
return Result<int, result::Error>{-1};
}).value();
std::cout << v3 << '\n';
MoveResult();
}