-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfake_variant.h
162 lines (145 loc) · 3.11 KB
/
fake_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
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*********************************************************
File Name: fakevariant.h
Author: Abby Cin
Mail: [email protected]
Created Time: Mon 21 Nov 2016 09:32:37 PM CST
**********************************************************/
#ifndef VARIANT_H_
#define VARIANT_H_
#include <functional>
namespace nm
{
namespace meta
{
struct Nil { };
template<typename T, typename U>
struct TypeList {
using Head = T;
using Tail = U;
};
template<typename... Args>
struct GenList;
template<>
struct GenList<Nil> {
using type = Nil;
};
template<typename T>
struct GenList<T> {
using type = TypeList<T, Nil>;
};
template<typename... Args>
struct GenList<Nil, Args...> // ignore `Nil` in Args
{
using type = typename GenList<Args...>::type;
};
template<typename T, typename... Args>
struct GenList<T, Args...> {
using type = TypeList<T, typename GenList<Args...>::type>;
};
template<typename, typename>
struct Remove;
template<typename T>
struct Remove<Nil, T> {
using type = Nil;
};
template<typename Tail, typename T>
struct Remove<TypeList<T, Tail>, T> {
using type = Tail;
};
template<typename Head, typename Tail, typename T>
struct Remove<TypeList<Head, Tail>, T> {
using type = TypeList<Head, typename Remove<Tail, T>::type>;
};
template<typename>
struct Unique;
template<>
struct Unique<Nil> {
using type = Nil;
};
template<typename Head, typename Tail>
struct Unique<TypeList<Head, Tail>> {
private:
using tmp = typename Unique<Tail>::type;
using tail = typename Remove<tmp, Head>::type;
public:
using type = TypeList<Head, tail>;
};
template<typename TL, template<typename> class Class>
class GenClasses;
template<typename T1, typename T2, template<typename> class Class>
class GenClasses<TypeList<T1, T2>, Class>
: public GenClasses<T1, Class>,
public GenClasses<T2, Class> { };
template<typename T, template<typename> class Class>
class GenClasses : public Class<T> { };
template<template<typename> class Class>
class GenClasses<Nil, Class> { };
}
template<typename U, typename... Args>
class FakeVariant {
public:
template<typename T>
bool set(const T &value)
{
return data_.invisible<T>::set(value);
}
template<typename T, typename... Paras>
bool set(Paras &&...paras)
{
return data_.invisible<T>::set(std::forward<Paras>(paras)...);
}
template<typename T>
const T &get() const
{
return data_.invisible<T>::get();
}
template<typename T>
bool valid() const
{
return data_.invisible<T>::valid();
}
private:
template<typename T>
class invisible {
public:
invisible() : value_ { nullptr }
{
}
~invisible()
{
clear();
}
template<typename... Paras>
bool set(Paras &&...paras)
{
bool res = valid();
clear();
value_ = new T(std::forward<Paras>(paras)...);
return !res;
}
const T &get() const
{
return *value_;
}
bool valid() const
{
return value_ != nullptr;
}
private:
T *value_;
void clear()
{
if (valid()) {
delete value_;
value_ = nullptr;
}
}
};
meta::GenClasses<
typename meta::Unique<
typename meta::GenList<U, Args...>::type>::type,
invisible>
data_;
};
}
#endif