forked from miki151/keeperrl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenum_variant.h
100 lines (80 loc) · 2.02 KB
/
enum_variant.h
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
#ifndef _ENUM_VARIANT_H
#define _ENUM_VARIANT_H
#include "serialization.h"
#include "debug.h"
template<typename U, typename Id, Id...value>
struct TypeAssign {
TypeAssign(const U& u, Id id) {
CHECK(hasValue(id));
}
template <typename V>
TypeAssign(const V& u, Id id) {
CHECK(!hasValue(id));
}
bool hasValue(Id id) {
for (Id i : {value...})
if (i == id)
return true;
return false;
}
};
struct EmptyThing {
bool operator == (const EmptyThing& other) const {
return true;
}
template <class Archive>
void serialize(Archive& ar, const unsigned int version) {
}
};
template<typename Id, typename Variant, typename... Assigns>
class EnumVariant {
public:
EnumVariant() {}
EnumVariant(Id i) : id(i) {
NO_RELEASE(boost::apply_visitor(CheckVisitor(id), values));
}
EnumVariant(const EnumVariant& other) = default;
template<typename U>
EnumVariant(Id i, U u) : id(i), values(u) {
NO_RELEASE(boost::apply_visitor(CheckVisitor(id), values));
}
Id getId() const {
return id;
}
template<typename U>
const U& get() const {
return boost::get<U>(values);
}
bool operator == (const EnumVariant& other) const {
return id == other.id && values == other.values;
}
bool operator != (const EnumVariant& other) const {
return !(*this == other);
}
template <class Archive>
void serialize(Archive& ar, const unsigned int version) {
ar & SVAR(id) & SVAR(values);
}
private:
template<typename T>
struct CheckId : public Assigns... {
CheckId(Id id, const T& u) : Assigns(u, id)... {
}
};
struct CheckVisitor : public boost::static_visitor<> {
public:
CheckVisitor(Id i) : id(i) {}
template<typename T>
void operator() (const T& t) const {
CheckId<T> tmp(id, t);
}
Id id;
};
Id SERIAL(id);
Variant SERIAL(values);
};
#define FIRST(first, ...) first
#define TYPES(...) boost::variant<EmptyThing, __VA_ARGS__>
#define ASSIGN(T, ...)\
TypeAssign<T, decltype(FIRST(__VA_ARGS__)), __VA_ARGS__>
#endif