YSTest: any.h 源文件

YSTest PreAlpha_b400_20130424 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
any.h
浏览该文件的文档.
1 ﻿/*
2 Copyright by FrankHB 2010 - 2013.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #ifndef YB_INC_ystdex_any_h_
29 #define YB_INC_ystdex_any_h_ 1
30
31 #include "type_op.hpp"
32 #include <memory> // for std::addressof, std::unique_ptr;
33 #include <typeinfo> // for typeid, std::bad_cast;
34
35 namespace ystdex
36 {
37
38 /*
39 \brief 用于表示任意不需要复制存储的非聚集 POD 类型。
40 \note POD 和聚集类型的含义参考 ISO C++11 。
41 \since build 352
42 \todo 确定整数和枚举类型的必要性。
43 */
44 union non_aggregate_pod
45 {
46 void* object_ptr;
47 const void* const_object_ptr;
48 volatile void* volatile_object_ptr;
49 const volatile void* const_volatile_object_ptr;
50 void(*function_ptr)();
51 int(non_aggregate_pod::*member_object_pointer);
52 void(non_aggregate_pod::*member_function_pointer)();
53 };
54
55
56 /*
57 \brief 任意 POD 类型存储。
58 \note POD 的含义参考 ISO C++11 。
59 \since build 351
60 */
61 template<typename _tPOD = typename aligned_storage<sizeof(void*)>::type>
62 union pod_storage
63 {
64 static_assert(is_pod<_tPOD>::value, "Non-POD underlying type found.");
65
66 typedef _tPOD underlying;
67
68 underlying object;
69 byte data[sizeof(underlying)];
70
72
73 pod_storage() = default;
74 template<typename _type>
75 pod_storage(_type&& x)
76 {
77 new(access()) typename remove_reference<_type>::type(yforward(x));
78 }
79
81 template<typename _type>
82 pod_storage&
83 operator=(_type&& x)
84 {
85 access<typename remove_reference<_type>::type>() = yforward(x);
86 return *this;
87 }
89
90 YB_PURE void*
91 access()
92 {
93 return &data[0];
94 }
95 yconstfn YB_PURE const void*
96 access() const
97 {
98 return &data[0];
99 }
100 template<typename _type>
101 YB_PURE _type&
102 access()
103 {
104 return *static_cast<_type*>(access());
105 }
106 template<typename _type>
107 yconstfn YB_PURE const _type&
108 access() const
109 {
110 return *static_cast<const _type*>(access());
111 }
112 };
113
114
121 class void_ref
122 {
123 private:
124 const volatile void* ptr;
125
126 public:
127 template<typename _type>
128 yconstfn
129 void_ref(_type& obj)
130 : ptr(&obj)
131 {}
132
133 template<typename _type>
134 yconstfn YB_PURE operator _type&()
135 {
136 return *static_cast<_type*>(&*this);
137 }
138
139 YB_PURE void*
140 operator&() const volatile
141 {
142 return const_cast<void*>(ptr);
143 }
144 };
145
146
148 namespace any_ops
149 {
150
155 class holder
156 {
157 public:
159
160 holder() = default;
161 holder(const holder&) = default;
162 holder(holder&&) = default;
164 virtual
165 ~holder()
166 {}
167
169 virtual void*
170 get() const = 0;
171
172 virtual holder*
173 clone() const = 0;
174
176 virtual const std::type_info&
177 type() const ynothrow = 0;
178 };
179
180
186 template<typename _type>
187 class value_holder : public holder
188 {
189 static_assert(is_object<_type>::value, "Non-object type found.");
190 static_assert(!(is_const<_type>::value || is_volatile<_type>::value),
191 "Cv-qualified type found.");
192
193 public:
195 typedef _type value_type;
196
197 protected:
199 mutable _type held;
200
201 public:
202 value_holder(const _type& value)
203 : held(value)
204 {}
210 value_holder(_type&& value) ynoexcept(ynoexcept(_type(std::move(value))))
211 : held(std::move(value))
212 {}
213
214 value_holder*
215 clone() const override
216 {
217 return new value_holder(held);
218 }
219
221 void*
222 get() const override
223 {
224 return std::addressof(held);
225 }
226
228 const std::type_info&
229 type() const ynothrow override
230 {
231 return typeid(_type);
232 }
233 };
234
235
242 template<typename _type>
243 class pointer_holder : public holder
244 {
245 static_assert(std::is_object<_type>::value, "Invalid type found.");
246
247 public:
249 typedef _type value_type;
250
251 protected:
253 _type* p_held;
254
255 public:
256 pointer_holder(_type* value)
257 : p_held(value)
258 {}
260
261 pointer_holder(const pointer_holder& h)
262 : pointer_holder(h.p_held ? new _type(*h.p_held) : nullptr)
263 {}
264 pointer_holder(pointer_holder&& h)
265 : p_held(h.p_held)
266 {
267 h.p_held = nullptr;
268 }
270 virtual
271 ~pointer_holder() ynothrow
272 {
273 delete p_held;
274 }
275
276 pointer_holder*
277 clone() const override
278 {
279 return new pointer_holder(*this);
280 }
281
283 void*
284 get() const override
285 {
286 return p_held;
287 }
288
290 const std::type_info&
291 type() const ynothrow override
292 {
293 return p_held ? typeid(_type) : typeid(void);
294 }
295 };
296
297
299 typedef std::uint32_t op_code;
300
302 enum base_op : op_code
303 {
305 no_op,
306 get_type,
307 get_ptr,
308 clone,
309 destroy,
310 get_holder_type,
311 get_holder_ptr,
313 end_base_op
314 };
315
316
318
319 typedef pod_storage<non_aggregate_pod> any_storage;
320 typedef void(*any_manager)(any_storage&, const any_storage&, op_code);
321
322
324 struct holder_tag
325 {};
327
328
333 template<typename _type, bool bStoredLocally = sizeof(_type)
334 <= sizeof(any_storage) && yalignof(_type) <= yalignof(any_storage)
335 && yalignof(any_storage) % yalignof(_type) == 0>
336 class value_handler
337 {
338 public:
340
341 typedef _type value_type;
342 typedef integral_constant<bool, bStoredLocally> local_storage;
343
344 static value_type*
345 get_pointer(const any_storage& s)
346 {
347 return const_cast<value_type*>(bStoredLocally ? std::addressof(
348 s.access<value_type>()) : s.access<const value_type*>());
349 }
351
353 static value_type&
354 get_reference(const any_storage& s)
355 {
356 yassume(get_pointer(s));
357
358 return *get_pointer(s);
359 }
360
362 static void
363 copy(any_storage& d, const any_storage& s, true_type)
364 {
365 new(d.access()) value_type(s.access<value_type>());
366 }
368 static void
369 copy(any_storage& d, const any_storage& s, false_type)
370 {
371 d = new value_type(*s.access<value_type*>());
372 }
373
375
376 static void
377 uninit(any_storage& d, true_type)
378 {
379 d.access<value_type>().~value_type();
380 }
381 static void
382 uninit(any_storage& d, false_type)
383 {
384 delete d.access<value_type*>();
385 }
386
387 template<typename _tValue>
388 static void
389 init(any_storage& d, _tValue&& x)
390 {
391 init_impl(d, yforward(x), local_storage());
392 }
394
395 private:
397
398 template<typename _tValue>
399 static void
400 init_impl(any_storage& d, _tValue&& x, true_type)
401 {
402 new(d.access()) value_type(yforward(x));
403 }
404 template<typename _tValue>
405 static void
406 init_impl(any_storage& d, _tValue&& x, false_type)
407 {
408 d = new value_type(yforward(x));
409 }
411
412 public:
414 static void
415 manage(any_storage& d, const any_storage& s, op_code op)
416 {
417 switch(op)
418 {
419 case get_type:
420 d = &typeid(value_type);
421 break;
422 case get_ptr:
423 d = get_pointer(s);
424 break;
425 case clone:
426 copy(d, s, local_storage());
427 break;
428 case destroy:
429 uninit(d, local_storage());
430 break;
431 case get_holder_type:
432 d = &typeid(void);
433 break;
434 case get_holder_ptr:
435 d = static_cast<holder*>(nullptr);
436 }
437 }
438 };
439
440
445 template<typename _type>
446 class ref_handler : public value_handler<_type*>
447 {
448 public:
449 typedef _type value_type;
450 typedef value_handler<value_type*> base;
451
453 static value_type*
454 get_pointer(const any_storage& s)
455 {
456 return base::get_reference(s);
457 }
458
460 static value_type&
461 get_reference(const any_storage& s)
462 {
463 yassume(get_pointer(s));
464
465 return *get_pointer(s);
466 }
467
468 static void
469 init(any_storage& d, std::reference_wrapper<value_type> x)
470 {
471 base::init(d, std::addressof(x.get()));
472 }
473
474 static void
475 manage(any_storage& d, const any_storage& s, op_code op)
476 {
477 switch(op)
478 {
479 case get_type:
480 d = &typeid(value_type);
481 break;
482 case get_ptr:
483 d = get_pointer(s);
484 break;
485 default:
486 base::manage(d, s, op);
487 }
488 }
489 };
490
491
496 template<typename _tHolder>
497 class holder_handler : public value_handler<_tHolder>
498 {
499 static_assert(is_convertible<_tHolder&, holder&>::value,
500 "Invalid holder type found.");
501
502 public:
503 typedef typename _tHolder::value_type value_type;
504 typedef value_handler<_tHolder> base;
505 typedef typename base::local_storage local_storage;
506
507 static value_type*
508 get_pointer(const any_storage& s)
509 {
510 return static_cast<value_type*>(base::get_pointer(s)->_tHolder::get());
511 }
512
513 private:
515 static void
516 init(any_storage& d, std::unique_ptr<_tHolder> p, true_type)
517 {
518 new(d.access()) _tHolder(std::move(*p));
519 }
521 static void
522 init(any_storage& d, std::unique_ptr<_tHolder> p, false_type)
523 {
524 d = p.release();
525 }
526
527 public:
529 static void
530 init(any_storage& d, std::unique_ptr<_tHolder> p)
531 {
532 init(d, std::move(p), local_storage());
533 }
534 static void
535 init(any_storage& d, _tHolder&& x)
536 {
537 base::init(d, std::move(x));
538 }
539 template<typename... _tParams>
540 static void
541 init(any_storage& d, _tParams&&... args)
542 {
543 init(d, _tHolder(yforward(args)...));
544 }
545
546 static void
547 manage(any_storage& d, const any_storage& s, op_code op)
548 {
549 switch(op)
550 {
551 case get_type:
552 d = &typeid(value_type);
553 break;
554 case get_ptr:
555 d = get_pointer(s);
556 break;
557 case clone:
558 base::copy(d, s, local_storage());
559 break;
560 case destroy:
561 base::uninit(d, local_storage());
562 break;
563 case get_holder_type:
564 d = &typeid(_tHolder);
565 break;
566 case get_holder_ptr:
567 d = static_cast<holder*>(base::get_pointer(s));
568 }
569 }
570 };
571
572 } // namespace any_ops;
573
574
584 class YB_API any
585 {
586 protected:
588
589 any_ops::any_storage storage;
590 any_ops::any_manager manager;
592
593 public:
595 yconstfn
596 any() ynothrow
597 : storage(), manager()
598 {}
600
601 template<typename _type, typename = typename
602 std::enable_if<!is_same<_type&, any&>::value, int>::type>
603 any(_type&& x)
604 : manager(any_ops::value_handler<typename
605 remove_reference<_type>::type>::manage)
606 {
607 any_ops::value_handler<typename remove_rcv<_type>::type>::init(storage,
608 yforward(x));
609 }
610 template<typename _type>
611 any(std::reference_wrapper<_type> x)
612 : manager(any_ops::ref_handler<_type>::manage)
613 {
614 any_ops::ref_handler<_type>::init(storage, x);
615 }
620 template<typename _tHolder>
621 any(any_ops::holder_tag, std::unique_ptr<_tHolder> p)
622 : manager(any_ops::holder_handler<_tHolder>::manage)
623 {
624 any_ops::holder_handler<_tHolder>::init(storage, std::move(p));
625 }
626 template<typename _type>
627 any(_type&& x, any_ops::holder_tag)
628 : manager(any_ops::holder_handler<any_ops::value_holder<typename
629 remove_rcv<_type>::type>>::manage)
630 {
631 any_ops::holder_handler<any_ops::value_holder<typename
632 remove_cv<_type>::type>>::init(storage, yforward(x));
633 }
635 any(const any&);
636 any(any&& a) ynothrow
637 : any()
638 {
639 a.swap(*this);
640 }
642 ~any();
643
644 template<typename _type>
645 any&
646 operator=(const _type& x)
647 {
648 any(x).swap(*this);
649 return *this;
650 }
655 any&
656 operator=(const any& a)
657 {
658 any(a).swap(*this);
659 return *this;
660 }
665 any&
666 operator=(any&& a) ynothrow
667 {
668 any(std::move(a)).swap(*this);
669 return *this;
670 }
671
672 bool
673 operator!() const ynothrow
674 {
675 return empty();
676 }
677
678 explicit
679 operator bool() const ynothrow
680 {
681 return !empty();
682 }
683
684 bool
685 empty() const ynothrow
686 {
687 return !manager;
688 }
689
691 void*
692 get() const ynothrow;
693
694 any_ops::holder*
695 get_holder() const;
696
697 void
698 clear() ynothrow;
699
700 void
701 swap(any& a) ynothrow;
702
704
705 template<typename _type>
706 _type*
707 target() ynothrow
708 {
709 return type() == typeid(_type) ? static_cast<_type*>(get()) : nullptr;
710 }
711 template<typename _type>
712 const _type*
713 target() const ynothrow
714 {
715 return type() == typeid(_type)
716 ? static_cast<const _type*>(get()) : nullptr;
717 }
719
721 const std::type_info&
722 type() const ynothrow;
723 };
724
725
732 class bad_any_cast : public std::bad_cast
733 {
734 private:
736 const char* from_name;
738 const char* to_name;
739
740 public:
742
743 bad_any_cast()
744 : std::bad_cast(),
745 from_name("unknown"), to_name("unknown")
746 {};
747 bad_any_cast(const std::type_info& from_type, const std::type_info& to_type)
748 : std::bad_cast(),
749 from_name(from_type.name()), to_name(to_type.name())
750 {}
751
752 const char*
753 from() const ynothrow
754 {
755 return from_name;
756 }
757
758 const char*
759 to() const ynothrow
760 {
761 return to_name;
762 }
764
765 virtual const char*
766 what() const ynothrow override
767 {
768 return "Failed conversion: any_cast.";
769 }
770 };
771
772
785 template<typename _tPointer>
786 inline _tPointer
787 any_cast(any* p) ynothrow
788 {
789 return p ? p->target<typename remove_pointer<_tPointer>::type>() : nullptr;
790 }
791 template<typename _tPointer>
792 inline _tPointer
793 any_cast(const any* p) ynothrow
794 {
795 return p ? p->target<typename remove_pointer<_tPointer>::type>() : nullptr;
796 }
798
803 template<typename _tValue>
804 inline _tValue
805 any_cast(any& x)
806 {
807 const auto tmp(any_cast<typename remove_reference<_tValue>::type*>(&x));
808
809 if(!tmp)
810 throw bad_any_cast(x.type(), typeid(_tValue));
811 return static_cast<_tValue>(*tmp);
812 }
813 template<typename _tValue>
814 _tValue
815 any_cast(const any& x)
816 {
817 const auto tmp(any_cast<typename remove_reference<_tValue>::type*>(&x));
818
819 if(!tmp)
820 throw bad_any_cast(x.type(), typeid(_tValue));
821 return static_cast<_tValue>(*tmp);
822 }
824
825
833 template<typename _type>
834 inline _type*
835 unsafe_any_cast(any* p)
836 {
837 yconstraint(p);
838
839 return static_cast<_type*>(p->get());
840 }
841
842 template<typename _type>
843 inline const _type*
844 unsafe_any_cast(const any* p)
845 {
846 yconstraint(p);
847
848 return static_cast<const _type*>(p->get());
849 }
851
852
858 struct pseudo_output
859 {
860 template<typename... _tParams>
861 inline pseudo_output&
862 operator=(_tParams&&...)
863 {
864 return *this;
865 }
866 };
867
868 } // namespace ystdex;
869
870
871 namespace std
872 {
873
878 inline void
879 swap(ystdex::any& x, ystdex::any& y) ynothrow
880 {
881 x.swap(y);
882 }
883
884 } // namespace std;
885
886 #endif
887