-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsandbox.cpp
147 lines (107 loc) · 2.59 KB
/
sandbox.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <iostream>
#include <type_traits>
#include <map>
#include <functional>
template<typename E>
class Enum {
public:
using value_type = E;
Enum() = default;
Enum(value_type v) : value_(v) {}
value_type& operator=(value_type v) { value_ = v; return value_; }
operator value_type() { return value_; }
friend bool operator==(Enum lhs, value_type rhs) {
return lhs.value_ == rhs;
}
friend bool operator==(value_type lhs, Enum rhs) {
return lhs == rhs.value_;
}
friend bool operator!=(Enum lhs, value_type rhs) {
return lhs.value_ != rhs;
}
friend bool operator!=(value_type lhs, Enum rhs) {
return lhs != rhs.value_;
}
bool operator==(Enum other) const {
return value_ == other.value_;
}
bool operator!=(Enum other) const {
return value_ != other.value_;
}
private:
value_type value_;
};
namespace wx {
enum class Winding {
kClockwise,
kCounterClockwise
};
template<typename Visitor>
static void AcceptVisitor(Visitor& v, Winding) {
v.VisitValue(Winding::kClockwise, "cw");
v.VisitValue(Winding::kCounterClockwise, "ccw");
}
} // namespace wx
namespace vis {
struct Vis {
template<typename E>
void Register() {
typename E::value_type v;
AcceptVisitor(*this, v);
}
template<typename E>
void VisitValue(E value, const char* name) {
static_assert(std::is_enum<E>::value, "Only enums are allowed");
static_assert(std::is_same<int, typename std::underlying_type<E>::type>::value, "Invalid underlying_type");
to_string[int(value)] = name;
to_value[name] = int(value);
}
std::map<int, std::string> to_string;
std::map<std::string, int> to_value;
};
} // namespace
void CheckEnum() {
vis::Vis v;
v.Register<Enum<wx::Winding>>();
// std::cerr << v.to_string[1] << std::endl;
Enum<wx::Winding> e;
e = wx::Winding::kCounterClockwise;
}
template<typename T>
void DumpType() {
std::cerr << __PRETTY_FUNCTION__ << std::endl;
}
template<typename... Ts>
struct InVersion;
template<typename T, typename V>
struct InVersion<T(V)> {
static void DumpIf(std::function<bool(int)> fn) {
if (fn(V::value)) {
DumpType<T>();
}
}
};
template<typename T, typename... Ts>
struct InVersion<T, Ts...> {
static void DumpIf(std::function<bool(int)> fn) {
InVersion<T>::DumpIf(fn);
InVersion<Ts...>::DumpIf(fn);
}
};
template<int N>
struct Version {
static constexpr int value = N;
};
template<typename... Ts>
struct List {};
using Version1 = Version<1>;
using Version2 = Version<2>;
void CheckVersion() {
List<int(Version1), bool(Version2)> ls;
InVersion<int(Version1), bool(Version2)>::DumpIf([](int n) -> bool {
return n > 0;
});
}
int main() {
CheckVersion();
}