-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtypes2.cpp
More file actions
122 lines (110 loc) · 4.88 KB
/
Copy pathtypes2.cpp
File metadata and controls
122 lines (110 loc) · 4.88 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
114
115
116
117
118
119
120
121
122
#include "types2.hpp"
#include <type_traits>
namespace Pawka {
namespace traits {
namespace {
struct No{};
template<typename T>
struct performable {
enum { value = !std::is_same<T, No>::value };
};
template <typename T>
struct is_num {
enum { value = std::is_same_v<T, int> || std::is_same_v<T, double> };
};
template<typename L, typename R> No operator+ (const L&, const R&);
template<typename L, typename R> No operator- (const L&, const R&);
template<typename L, typename R> No operator* (const L&, const R&);
template<typename L, typename R> No operator/ (const L&, const R&);
template<typename L, typename R> No operator< (const L&, const R&);
template<typename L, typename R> No operator<=(const L&, const R&);
template<typename L, typename R> No operator> (const L&, const R&);
template<typename L, typename R> No operator>=(const L&, const R&);
template<typename L, typename R> No operator!=(const L&, const R&);
template<typename L, typename R> No operator==(const L&, const R&);
} // namespace
template<typename L, typename R>
struct has {
enum {
assign = is_num<L>::value ^ is_num<R>::value,
plus = performable<decltype(std::declval<L>() + std::declval<R>())>::value,
minus = performable<decltype(std::declval<L>() - std::declval<R>())>::value,
mul = performable<decltype(std::declval<L>() * std::declval<R>())>::value,
div = performable<decltype(std::declval<L>() / std::declval<R>())>::value,
lt = performable<decltype(std::declval<L>() < std::declval<R>())>::value,
le = performable<decltype(std::declval<L>() <= std::declval<R>())>::value,
gt = performable<decltype(std::declval<L>() > std::declval<R>())>::value,
ge = performable<decltype(std::declval<L>() >= std::declval<R>())>::value,
ne = performable<decltype(std::declval<L>() != std::declval<R>())>::value,
eq = performable<decltype(std::declval<L>() == std::declval<R>())>::value,
};
};
} // namespace traits
Value& Value::operator= (const Value& other) {
std::visit([](auto& lhs, const auto& rhs) {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::assign) lhs = rhs;
else throw "Unsupported";
}, val, other.val);
return *this;
}
Value Value::operator+ (const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::plus) return {lhs + rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator- (const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::minus) return {lhs - rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator* (const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::mul) return {lhs * rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator/ (const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::div) return {lhs / rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator< (const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::lt) return {lhs < rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator<=(const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::le) return {lhs <= rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator> (const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::gt) return {lhs > rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator>=(const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::ge) return {lhs >= rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator!=(const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::ne) return {lhs != rhs};
throw "Unsopported";
}, val, other.val);
}
Value Value::operator==(const Value& other) const {
return std::visit([](const auto& lhs, const auto& rhs) -> Value {
if constexpr (traits::has<decltype(lhs), decltype(rhs)>::eq) return {lhs == rhs};
throw "Unsopported";
}, val, other.val);
}
} // namespace Pawka