SimpleWindow
载入中...
搜索中...
未找到
Variant.h
1#pragma once
2
3#include "Reflection.h"
4
5namespace sw
6{
19
36 {
37 private:
41 std::unique_ptr<DynamicObject> _obj;
42
46 DynamicObject *(*_cloner)(const DynamicObject &) = nullptr;
47
48 public:
52 Variant() = default;
53
57 Variant(std::nullptr_t) noexcept
58 {
59 }
60
69 {
70 if (ref.ptr != nullptr) {
71 _obj.reset(new BoxedObject<ObjectRef>(ref));
73 }
74 }
75
81 template <
82 typename T,
83 typename std::enable_if<!std::is_same<Variant, typename std::decay<T>::type>::value, int>::type = 0>
84 Variant(T &&obj)
85 {
86 Reset(std::forward<T>(obj));
87 }
88
94 {
95 if (other._obj != nullptr) {
96 _obj.reset(other._cloner(*other._obj));
97 _cloner = other._cloner;
98 }
99 }
100
105 : _obj(std::move(other._obj)), _cloner(other._cloner)
106 {
107 other._cloner = nullptr;
108 }
109
115 {
116 Reset(other);
117 return *this;
118 }
119
124 {
125 Reset(std::move(other));
126 return *this;
127 }
128
133 explicit operator bool() const noexcept
134 {
135 return _obj != nullptr;
136 }
137
143 {
144 return _obj == nullptr;
145 }
146
152 {
153 return _obj != nullptr;
154 }
155
163 bool ReferenceEquals(const Variant &other) const noexcept
164 {
165 const DynamicObject *a = Object();
166 const DynamicObject *b = other.Object();
167
168 if (a == nullptr && b == nullptr) {
169 return true;
170 }
171 if (a == nullptr || b == nullptr) {
172 return false;
173 }
174 return a->ReferenceEquals(*b);
175 }
176
181 {
182 _obj.reset();
183 _cloner = nullptr;
184 }
185
189 void Reset(std::nullptr_t) noexcept
190 {
191 Reset();
192 }
193
202 {
203 if (ref.ptr == nullptr) {
204 Reset();
205 } else {
206 _obj.reset(new BoxedObject<ObjectRef>(ref));
208 }
209 }
210
215 void Reset(const Variant &other)
216 {
217 if (this == &other) {
218 return;
219 }
220
221 if (other._obj == nullptr) {
222 Reset();
223 } else {
224 _obj.reset(other._cloner(*other._obj));
225 _cloner = other._cloner;
226 }
227 }
228
232 void Reset(Variant &&other) noexcept
233 {
234 if (this != &other) {
235 _obj = std::move(other._obj);
236 _cloner = other._cloner;
237 other._cloner = nullptr;
238 }
239 }
240
246 template <typename T>
247 auto Reset(T &&obj)
248 -> typename std::enable_if<
249 !std::is_same<Variant, typename std::decay<T>::type>::value &&
250 std::is_base_of<DynamicObject, typename std::decay<T>::type>::value>::type
251 {
252 using U = typename std::decay<T>::type;
253 _obj.reset(new U(std::forward<T>(obj)));
255 }
256
262 template <typename T>
263 auto Reset(T &&obj)
264 -> typename std::enable_if<
265 !std::is_same<Variant, typename std::decay<T>::type>::value &&
266 !std::is_base_of<DynamicObject, typename std::decay<T>::type>::value>::type
267 {
268 using U = typename std::decay<T>::type;
269 _obj.reset(new BoxedObject<U>(std::forward<T>(obj)));
271 }
272
280 {
281 if (_obj == nullptr) {
282 return nullptr;
283 }
284
285 ObjectRef *ref = nullptr;
286
287 if (_obj->IsType<ObjectRef>(&ref)) {
288 return ref->ptr;
289 }
290 return _obj.get();
291 }
292
300 {
301 if (_obj == nullptr) {
302 return nullptr;
303 }
304
305 const ObjectRef *ref = nullptr;
306
307 if (_obj->IsType<ObjectRef>(&ref)) {
308 return ref->ptr;
309 }
310 return _obj.get();
311 }
312
319 std::type_index GetType() const
320 {
321 const DynamicObject *p = Object();
322 return p == nullptr ? typeid(void) : p->GetType();
323 }
324
332 template <typename T>
333 bool IsType(T **pout = nullptr)
334 {
336
337 if (p == nullptr) {
338 if (pout != nullptr) {
339 *pout = nullptr;
340 }
341 return false;
342 }
343 return p->IsType<T>(pout);
344 }
345
353 template <typename T>
354 bool IsType(const T **pout = nullptr) const
355 {
356 const DynamicObject *p = Object();
357
358 if (p == nullptr) {
359 if (pout != nullptr) {
360 *pout = nullptr;
361 }
362 return false;
363 }
364 return p->IsType<T>(pout);
365 }
366
374 template <typename T>
376 {
378
379 if (p == nullptr) {
380 throw std::bad_cast();
381 }
382 return p->DynamicCast<T>();
383 }
384
392 template <typename T>
393 const T &DynamicCast() const
394 {
395 const DynamicObject *p = Object();
396
397 if (p == nullptr) {
398 throw std::bad_cast();
399 }
400 return p->DynamicCast<T>();
401 }
402
411 template <typename T>
413 {
415
416 if (p == nullptr) {
417 throw std::bad_cast();
418 }
419 return p->UnsafeCast<T>();
420 }
421
430 template <typename T>
431 const T &UnsafeCast() const
432 {
433 const DynamicObject *p = Object();
434
435 if (p == nullptr) {
436 throw std::bad_cast();
437 }
438 return p->UnsafeCast<T>();
439 }
440
441 private:
446 template <typename T>
447 auto ResetCloner()
448 -> typename std::enable_if<std::is_copy_constructible<T>::value && std::is_base_of<DynamicObject, T>::value>::type
449 {
450 _cloner = [](const DynamicObject &other) -> DynamicObject * {
451 return new T(other.UnsafeCast<T>());
452 };
453 }
454
459 template <typename T>
460 auto ResetCloner()
461 -> typename std::enable_if<std::is_copy_constructible<T>::value && !std::is_base_of<DynamicObject, T>::value>::type
462 {
463 _cloner = [](const DynamicObject &other) -> DynamicObject * {
464 return new BoxedObject<T>(other.UnsafeCast<BoxedObject<T>>());
465 };
466 }
467
474 template <typename T>
475 auto ResetCloner()
476 -> typename std::enable_if<!std::is_copy_constructible<T>::value>::type
477 {
478 _cloner = [](const DynamicObject &other) -> DynamicObject * {
479 throw std::runtime_error("Object is not copy constructible.");
480 };
481 }
482
483 public:
493 template <typename T, typename... Args>
494 static auto MakeVal(Args &&...args)
495 -> typename std::enable_if<
496 !std::is_same<T, Variant>::value &&
497 std::is_base_of<DynamicObject, T>::value,
498 Variant>::type
499 {
500 Variant v;
501 v._obj.reset(new T(std::forward<Args>(args)...));
502 v.ResetCloner<T>();
503 return v;
504 }
505
515 template <typename T, typename... Args>
516 static auto MakeVal(Args &&...args)
517 -> typename std::enable_if<
518 !std::is_same<T, Variant>::value &&
519 !std::is_base_of<DynamicObject, T>::value,
520 Variant>::type
521 {
522 Variant v;
523 v._obj.reset(new BoxedObject<T>(std::forward<Args>(args)...));
524 v.ResetCloner<T>();
525 return v;
526 }
527
537 {
538 DynamicObject *p = v.Object();
539 return p == nullptr ? Variant{} : MakeRef(*p);
540 }
541
550 template <typename T>
551 static auto MakeRef(T &obj)
552 -> typename std::enable_if<
553 !std::is_same<T, Variant>::value &&
554 std::is_base_of<DynamicObject, T>::value,
555 Variant>::type
556 {
557 Variant v;
558 v._obj.reset(new BoxedObject<ObjectRef>(ObjectRef{&obj}));
559 v.ResetCloner<ObjectRef>();
560 return v;
561 }
562
571 template <typename T>
572 static auto MakeRef(T &obj)
573 -> typename std::enable_if<
574 !std::is_same<T, Variant>::value &&
575 !std::is_base_of<DynamicObject, T>::value,
576 Variant>::type
577 {
578 Variant v;
579 v._obj.reset(new BoxedObject<T>(BoxedObject<T>::MakeRef(&obj)));
580 v.ResetCloner<T>();
581 return v;
582 }
583 };
584}
装箱对象模板类声明
Definition Reflection.h:21
动态对象基类
Definition Reflection.h:27
值转换器接口
Definition IValueConverter.h:14
通用变体类型容器,类型擦除地持有任意类型对象
Definition Variant.h:36
static auto MakeVal(Args &&...args) -> typename std::enable_if< !std::is_same< T, Variant >::value &&!std::is_base_of< DynamicObject, T >::value, Variant >::type
就地构造一个值语义的Variant(非DynamicObject类型重载)
Definition Variant.h:516
const T & UnsafeCast() const
将Variant对象转换为指定类型的常量引用
Definition Variant.h:431
static Variant MakeRef(Variant &v)
创建一个对另一Variant内部对象的引用Variant(Variant转发重载)
Definition Variant.h:536
std::type_index GetType() const
获取内部对象的类型信息
Definition Variant.h:319
bool ReferenceEquals(const Variant &other) const noexcept
判断两Variant是否引用同一对象(指针身份比较)
Definition Variant.h:163
Variant(T &&obj)
通用构造函数,接受任意类型的对象(值语义)
Definition Variant.h:84
bool HasValue() const noexcept
判断Variant对象是否包含值
Definition Variant.h:151
void Reset(Variant &&other) noexcept
重置Variant对象为另一个Variant对象的值
Definition Variant.h:232
void Reset() noexcept
重置Variant对象为空
Definition Variant.h:180
static auto MakeVal(Args &&...args) -> typename std::enable_if< !std::is_same< T, Variant >::value &&std::is_base_of< DynamicObject, T >::value, Variant >::type
就地构造一个值语义的Variant(DynamicObject派生类型重载)
Definition Variant.h:494
bool IsType(T **pout=nullptr)
判断当前Variant存储的对象是否为指定类型
Definition Variant.h:333
const DynamicObject * Object() const noexcept
获取内部动态对象的常量指针
Definition Variant.h:299
Variant(Variant &&other) noexcept
移动构造函数
Definition Variant.h:104
auto Reset(T &&obj) -> typename std::enable_if< !std::is_same< Variant, typename std::decay< T >::type >::value &&std::is_base_of< DynamicObject, typename std::decay< T >::type >::value >::type
重置Variant对象为指定类型的对象
Definition Variant.h:247
static auto MakeRef(T &obj) -> typename std::enable_if< !std::is_same< T, Variant >::value &&!std::is_base_of< DynamicObject, T >::value, Variant >::type
创建一个对外部对象的引用Variant(非DynamicObject类型重载)
Definition Variant.h:572
static auto MakeRef(T &obj) -> typename std::enable_if< !std::is_same< T, Variant >::value &&std::is_base_of< DynamicObject, T >::value, Variant >::type
创建一个对外部对象的引用Variant(DynamicObject派生类型重载)
Definition Variant.h:551
bool IsNull() const noexcept
判断Variant对象是否为空
Definition Variant.h:142
DynamicObject * Object() noexcept
获取内部动态对象指针
Definition Variant.h:279
Variant(std::nullptr_t) noexcept
从nullptr构造一个空的Variant对象
Definition Variant.h:57
Variant(ObjectRef ref)
以引用语义构造Variant
Definition Variant.h:68
const T & DynamicCast() const
将Variant对象动态转换为指定类型的常量引用
Definition Variant.h:393
Variant & operator=(Variant &&other) noexcept
移动赋值运算符
Definition Variant.h:123
Variant & operator=(const Variant &other)
拷贝赋值运算符
Definition Variant.h:114
T & DynamicCast()
将Variant对象动态转换为指定类型的引用
Definition Variant.h:375
Variant()=default
默认构造函数,创建一个空的Variant对象
bool IsType(const T **pout=nullptr) const
判断当前Variant存储的对象是否为指定类型
Definition Variant.h:354
void Reset(std::nullptr_t) noexcept
重置Variant对象为空
Definition Variant.h:189
auto Reset(T &&obj) -> typename std::enable_if< !std::is_same< Variant, typename std::decay< T >::type >::value &&!std::is_base_of< DynamicObject, typename std::decay< T >::type >::value >::type
重置Variant对象为指定类型的对象
Definition Variant.h:263
T & UnsafeCast()
将Variant对象转换为指定类型的引用
Definition Variant.h:412
void Reset(ObjectRef ref)
重置Variant对象为指定的引用标记
Definition Variant.h:201
Variant(const Variant &other)
拷贝构造函数
Definition Variant.h:93
void Reset(const Variant &other)
重置Variant对象为另一个Variant对象的值
Definition Variant.h:215
SimpleWindow框架的顶级命名空间,所有公共类型、控件、枚举和工具函数均定义于此。
Definition Alignment.h:4
动态对象引用标记类型
Definition Variant.h:13
DynamicObject * ptr
被引用的DynamicObject指针
Definition Variant.h:17