17 {
18 public:
20 static constexpr Tag
Empty = 0;
21
22
23
25
27 contains_type<T, Types...>
::value>::type>
30 }
31
36 }
37
39 if (!other.empty()) {
40 copy_construct_from(other);
41 }
42 }
43
45 if (!other.empty()) {
46 move_construct_from(other);
47
49 }
50 }
51
53
54 variant &operator=(
const variant &other)
FL_NOEXCEPT {
55 if (this != &other) {
56 reset();
57 if (!other.empty()) {
58 copy_construct_from(other);
59 }
60 }
61 return *this;
62 }
63
65 if (this != &other) {
66 reset();
67 if (!other.empty()) {
68 move_construct_from(other);
69
71 }
72 }
73 return *this;
74 }
75
79
80
82 reset();
84 return *this;
85 }
86
90 reset();
92 return *this;
93 }
94
95
96
97 template <typename T, typename... Args>
100 reset();
102 return *ptr<T>();
103 }
104
106 if (!empty()) {
107 destroy_current();
109 }
110 }
111
114
115 template <
typename T>
bool is() const
FL_NOEXCEPT {
116 return _tag == type_to_tag<T>();
117 }
118
120 if (!is<T>()) return nullptr;
121
122
124 }
125
126 template <
typename T>
const T *ptr() const
FL_NOEXCEPT {
127 if (!is<T>()) return nullptr;
128
129
131 }
132
139
140
141 return *ptr<T>();
142 }
143
150
151
152 return *ptr<T>();
153 }
154
155 template <
typename T>
bool equals(
const T &other)
const FL_NOEXCEPT {
156 if (auto p = ptr<T>()) {
157 return *p == other;
158 }
159 return false;
160 }
161
162
163 template <
typename Visitor>
void visit(Visitor &visitor)
FL_NOEXCEPT {
165 return;
166
167
168 using Fn = void (*)(void *, Visitor &);
169
170
171
172
173 static constexpr Fn table[] = {
174 &variant::template visit_fn<Types, Visitor>...};
175
176
177
178 size_t index = _tag - 1;
179 if (index < sizeof...(Types)) {
180 table[index](&_storage, visitor);
181 }
182 }
183
184 template <
typename Visitor>
void visit(Visitor &visitor)
const FL_NOEXCEPT {
186 return;
187
188
189 using Fn = void (*)(const void *, Visitor &);
190
191
192 static constexpr Fn table[] = {
193 &variant::template visit_fn_const<Types, Visitor>...};
194
195
196
197 size_t index = _tag - 1;
198 if (index < sizeof...(Types)) {
199 table[index](&_storage, visitor);
200 }
201 }
202
203 private:
204
205 template <typename T, typename Visitor>
206 static void visit_fn(
void *storage, Visitor &v)
FL_NOEXCEPT {
207
208
210 v.accept(*typed_ptr);
211 }
212
213 template <typename T, typename Visitor>
214 static void visit_fn_const(
const void *storage, Visitor &v)
FL_NOEXCEPT {
215
216
218 v.accept(*typed_ptr);
219 }
220
221
223 using Fn = void (*)(void *);
226 static constexpr Fn table[] = {&variant::template destroy_fn<Types>...};
228 table[_tag - 1](&_storage);
229 }
231 }
232
233 template <
typename T>
static void destroy_fn(
void *storage)
FL_NOEXCEPT {
234
235
237 typed_ptr->~T();
238 }
239
240
241 void copy_construct_from(
const variant &other)
FL_NOEXCEPT {
242 using Fn = void (*)(void *, const variant &);
245 static constexpr Fn table[] = {&variant::template copy_fn<Types>...};
246 table[other._tag - 1](&_storage, other);
248 _tag = other._tag;
249 }
250
251 template <typename T>
252 static void copy_fn(
void *storage,
const variant &other)
FL_NOEXCEPT {
253
254
256 new (storage) T(*source_ptr);
257 }
258
259
260 void move_construct_from(variant &other)
FL_NOEXCEPT {
261 using Fn = void (*)(void *, variant &);
264 static constexpr Fn table[] = {&variant::template move_fn<Types>...};
265 table[other._tag - 1](&_storage, other);
267 _tag = other._tag;
268 other.reset();
269 }
270
271 template <
typename T>
static void move_fn(
void *storage, variant &other)
FL_NOEXCEPT {
272
273
275 new (storage) T(
fl::move(*source_ptr));
276 }
277
278
279
280
281
282
283
284
285 template <
typename T>
static constexpr Tag type_to_tag()
FL_NOEXCEPT {
286 return type_to_tag_impl<T, Types...>
::value;
287 }
288
289
290 template <typename T, typename... Ts> struct type_to_tag_impl;
291
292 template <typename T> struct type_to_tag_impl<T> {
293 static constexpr Tag value = 0;
294 };
295
296 template <typename T, typename U, typename... Rest>
297 struct type_to_tag_impl<T, U, Rest...> {
298 static constexpr Tag value =
300 ? 1
301 : (type_to_tag_impl<T, Rest...>::value == 0
302 ? 0
303 : type_to_tag_impl<T, Rest...>::value + 1);
304 };
305
306 template <
typename T,
typename... Args>
void construct(Args &&...
args)
FL_NOEXCEPT {
308 _tag = type_to_tag<T>();
309 }
310
312
313 Tag _tag;
314};
A fixed-size array implementation similar to std::array.
constexpr T && forward(typename remove_reference< T >::type &t) FL_NOEXCEPT
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
constexpr int type_rank< T >::value
To * bit_cast_ptr(void *storage) FL_NOEXCEPT
pair_element< I, T1, T2 >::type & get(pair< T1, T2 > &p) FL_NOEXCEPT
#define FL_ALIGN_AS_T(expr)
#define FL_DISABLE_WARNING(warning)
#define FL_DISABLE_WARNING_PUSH
#define FL_DISABLE_WARNING_POP