Adobe Source Libraries 1.49.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
any_regular.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6/**************************************************************************************************/
7
8
9#ifndef ADOBE_ANY_REGULAR_HPP
10#define ADOBE_ANY_REGULAR_HPP
11
12#include <adobe/config.hpp>
13
15
16#include <cstdint>
17#include <type_traits>
18
19#include <boost/concept_check.hpp>
20#include <boost/mpl/bool.hpp>
21#include <boost/mpl/if.hpp>
22#include <boost/noncopyable.hpp>
23#include <boost/operators.hpp>
24
25#include <adobe/conversion.hpp>
26#include <adobe/empty.hpp>
27#include <adobe/memory.hpp>
30#include <adobe/typeinfo.hpp>
31
32#include <adobe/implementation/swap.hpp>
33
34#if defined(ADOBE_STD_SERIALIZATION)
35#include <adobe/iomanip.hpp>
36#endif
37
38/**************************************************************************************************/
39
40namespace adobe {
41
45
46
58
70
71
78
79
80/**************************************************************************************************/
81
82namespace implementation {
83
84enum { vtable_version = 2 };
85
86/**************************************************************************************************/
87
88struct any_regular_interface_t;
89
90struct vtable_t {
91 typedef any_regular_interface_t interface_type;
92
93 std::uintptr_t version;
94 void (*destruct)(const interface_type&);
95 const std::type_info& (*type_info)(const interface_type&);
96 interface_type* (*clone)(const interface_type&, void*);
97 interface_type* (*move_clone)(interface_type&, void*);
98 void (*assign)(interface_type&, const interface_type&);
99 bool (*equals)(const interface_type&, const interface_type&);
100 void (*exchange)(interface_type&, interface_type&);
101 void (*serialize)(const interface_type&, std::ostream&);
102};
103
104// Ensure that the vtable_t has a fixed layout regardless of alignment or packing.
105
106static_assert(sizeof(vtable_t) == 9 * sizeof(void*));
107
108/**************************************************************************************************/
109
110union pad_vtable_t {
111 const vtable_t* vtable_m;
112 double pad_m; // unused padding
113};
114
115static_assert(sizeof(pad_vtable_t) == sizeof(double));
116
117/**************************************************************************************************/
118
119struct any_regular_interface_t {
120 typedef any_regular_interface_t interface_type;
121
122 any_regular_interface_t(const vtable_t& x) { object_m.vtable_m = &x; }
123
124 pad_vtable_t object_m;
125
126 void destruct() const { return object_m.vtable_m->destruct(*this); }
127 const std::type_info& type_info() const { return object_m.vtable_m->type_info(*this); }
128 interface_type* clone(void* x) const { return object_m.vtable_m->clone(*this, x); }
129 interface_type* move_clone(void* x) { return object_m.vtable_m->move_clone(*this, x); }
130 void assign(const interface_type& x) { object_m.vtable_m->assign(*this, x); }
131 bool equals(const interface_type& x) const { return object_m.vtable_m->equals(*this, x); }
132 void exchange(interface_type& x) { object_m.vtable_m->exchange(*this, x); }
133 void serialize(std::ostream& s) const { object_m.vtable_m->serialize(*this, s); }
134};
135
136/**************************************************************************************************/
137
138template <typename T> // T models Regular
139struct any_regular_model_local : any_regular_interface_t, boost::noncopyable {
140 typedef any_regular_interface_t interface_type;
141
142 T object_m;
143
144 static const vtable_t vtable_s;
145
146 any_regular_model_local() : interface_type(vtable_s), object_m() {}
147
148 explicit any_regular_model_local(T x) : interface_type(vtable_s), object_m(std::move(x)) {}
149
150 static const any_regular_model_local& self(const interface_type& x) {
151 return static_cast<const any_regular_model_local&>(x);
152 }
153
154 static any_regular_model_local& self(interface_type& x) {
155 return static_cast<any_regular_model_local&>(x);
156 }
157
158 static const std::type_info& type_info(const interface_type&) { return typeid(T); }
159
160 static void destruct(const interface_type& x) { self(x).~any_regular_model_local(); }
161
162 static interface_type* clone(const interface_type& x, void* storage) {
163 return ::new (storage) any_regular_model_local(self(x).object_m);
164 }
165
166 static interface_type* move_clone(interface_type& x, void* storage) {
167 return ::new (storage) any_regular_model_local(std::move(self(x).object_m));
168 }
169
170 static void assign(interface_type& x, const interface_type& y) {
171 self(x).object_m = self(y).object_m;
172 }
173
174 static bool equals(const interface_type& x, const interface_type& y) {
175 return self(x).object_m == self(y).object_m;
176 }
177
178 static void exchange(interface_type& x, interface_type& y) {
179 swap(self(x).object_m, self(y).object_m);
180 }
181
182 static void serialize(const interface_type& x, std::ostream& s) { s << format(self(x).get()); }
183
184 const T& get() const { return object_m; }
185 T& get() { return object_m; }
186};
187
188static_assert(sizeof(any_regular_model_local<double>) == 16);
189
190template <typename T>
191const vtable_t any_regular_model_local<T>::vtable_s = {
192 vtable_version,
193 &any_regular_model_local::destruct,
194 &any_regular_model_local::type_info,
195 &any_regular_model_local::clone,
196 &any_regular_model_local::move_clone,
197 &any_regular_model_local::assign,
198 &any_regular_model_local::equals,
199 &any_regular_model_local::exchange,
200 &any_regular_model_local::serialize,
201};
202
203template <typename T> // T models Regular
204struct any_regular_model_remote : any_regular_interface_t, boost::noncopyable {
205 BOOST_CLASS_REQUIRE(T, adobe, RegularConcept);
206
207 typedef any_regular_interface_t interface_type;
208
209 struct object_t;
210 typedef capture_allocator<object_t> allocator_type;
211
212 struct object_t : boost::noncopyable {
213 aligned_storage<allocator_type> alloc_m;
214 T data_m;
215 };
216
217 static object_t* new_move(T& x) {
218 allocator_type a;
219 object_t* result = a.allocate(1);
220 adobe::construct_at(&result->alloc_m, aligned_storage<allocator_type>(a));
221 adobe::construct_at(&result->data_m, std::move(x));
222 return result;
223 }
224
225 object_t* object_ptr_m;
226
227 static const vtable_t vtable_s;
228
229 explicit any_regular_model_remote(T x) : interface_type(vtable_s), object_ptr_m(new_move(x)) {}
230
231 any_regular_model_remote(any_regular_model_remote&& x) noexcept
232 : interface_type(vtable_s), object_ptr_m(x.object_ptr_m) {
233 x.object_ptr_m = 0;
234 }
235
236 ~any_regular_model_remote() {
237 if (object_ptr_m) {
238 allocator_type a = object_ptr_m->alloc_m.get();
239 destroy(&object_ptr_m->alloc_m);
240 destroy(&object_ptr_m->data_m);
241 a.deallocate(object_ptr_m, 1);
242 }
243 }
244
245 static const any_regular_model_remote& self(const interface_type& x) {
246 return static_cast<const any_regular_model_remote&>(x);
247 }
248
249 static any_regular_model_remote& self(interface_type& x) {
250 return static_cast<any_regular_model_remote&>(x);
251 }
252
253 static const std::type_info& type_info(const interface_type&) { return typeid(T); }
254
255 static void destruct(const interface_type& x) { return self(x).~any_regular_model_remote(); }
256
257 static interface_type* clone(const interface_type& x, void* storage) {
258 return ::new (storage) any_regular_model_remote(self(x).get());
259 }
260
261 static interface_type* move_clone(interface_type& x, void* storage) {
262 return ::new (storage) any_regular_model_remote(std::move(self(x)));
263 }
264
265 static void assign(interface_type& x, const interface_type& y) {
266 self(x).get() = self(y).get();
267 }
268
269 static bool equals(const interface_type& x, const interface_type& y) {
270 return self(x).get() == self(y).get();
271 }
272
273 static void exchange(interface_type& x, interface_type& y) {
274 return swap(self(x).object_ptr_m, self(y).object_ptr_m);
275 }
276
277 static void serialize(const interface_type& x, std::ostream& s) { s << format(self(x).get()); }
278
279 const T& get() const { return object_ptr_m->data_m; }
280 T& get() { return object_ptr_m->data_m; }
281};
282
283static_assert(sizeof(any_regular_model_remote<double>) <= 16);
284
285template <typename T>
286const vtable_t any_regular_model_remote<T>::vtable_s = {
287 vtable_version,
288 &any_regular_model_remote::destruct,
289 &any_regular_model_remote::type_info,
290 &any_regular_model_remote::clone,
291 &any_regular_model_remote::move_clone,
292 &any_regular_model_remote::assign,
293 &any_regular_model_remote::equals,
294 &any_regular_model_remote::exchange,
295 &any_regular_model_remote::serialize,
296};
297
298/**************************************************************************************************/
299
300} // namespace implementation
301
302/**************************************************************************************************/
303
304inline namespace version_1 {
305
306/**************************************************************************************************/
307
355
356class any_regular_t : boost::equality_comparable<any_regular_t, any_regular_t> {
357 typedef implementation::any_regular_interface_t interface_type;
358 typedef double storage_t[2];
359
360#ifndef ADOBE_NO_DOCUMENTATION
361
362 template <typename T>
363 struct traits {
364 typedef typename promote<T>::type promote_type;
365 BOOST_CLASS_REQUIRE(promote_type, adobe, RegularConcept);
366
367 typedef promote_type& reference_type;
368 typedef const promote_type& const_reference_type;
369
370 typedef implementation::any_regular_model_local<promote_type> regular_model_local_type;
371 typedef implementation::any_regular_model_remote<promote_type> regular_model_remote_type;
372
373 typedef boost::mpl::bool_<(sizeof(regular_model_local_type) <= sizeof(storage_t)) &&
374 std::is_nothrow_move_constructible<promote_type>::value>
375 use_local_type;
376
377 typedef typename boost::mpl::if_<use_local_type, regular_model_local_type,
378 regular_model_remote_type>::type model_type;
379
380 typedef
381 typename boost::mpl::if_c<std::is_same<promote_type, T>::value, reference_type, T>::type
382 result_type;
383
384 typedef typename boost::mpl::if_c<std::is_same<promote_type, T>::value,
385 const_reference_type, T>::type const_result_type;
386 };
387
388 template <typename T>
389 struct helper;
390 template <typename T>
391 friend struct helper;
392
393#endif
394
395public:
402 any_regular_t() { ::new (storage()) traits<empty_t>::model_type(); }
403
404 any_regular_t(const any_regular_t& x) { x.object().clone(storage()); }
405
406 any_regular_t(any_regular_t&& x) noexcept { x.object().move_clone(storage()); }
407
409 object().destruct();
410 x.object().move_clone(storage());
411 return *this;
412 }
413
414 ~any_regular_t() { object().destruct(); }
416
418
425
426 template <typename T>
428 ::new (storage()) typename traits<T>::model_type(std::move(x));
429 }
430
432
434
443
444 template <typename T>
445 bool cast(T& x) const {
446 if (type_info() != typeid(typename promote<T>::type))
447 return false;
448 x = cast<T>();
449 return true;
450 }
451
452 template <typename T>
453 typename traits<T>::const_result_type cast() const {
454 return helper<T>::cast(*this);
455 }
456
465
466 template <typename T>
467 typename traits<T>::result_type cast() {
468 return helper<T>::cast(*this);
469 }
470
472
474
483
484 template <typename T>
486 object().destruct();
487 ::new (storage()) typename traits<T>::model_type(std::move(x));
488 return *this;
489 }
490
492 object().destruct();
493 x.object().move_clone(storage());
494 return *this;
495 }
496
498
500
505
506 const std::type_info& type_info() const { return object().type_info(); }
507
511
513
514
515 template <typename T>
516 struct transform {
517 typedef typename traits<T>::promote_type result_type;
518
519 typename traits<T>::result_type operator()(any_regular_t& x) const { return x.cast<T>(); }
520
521 typename traits<T>::const_result_type operator()(const any_regular_t& x) const {
522 return x.cast<T>();
523 }
524 };
525
526#if defined(ADOBE_STD_SERIALIZATION)
527 // Problem: We want 'any' to be serializable. But 'any' can be implicitly
528 // constructed from a type T making it difficult to determine if T is
529 // serializable or if T converted to an 'any' is serializable. We wrap the
530 // serialization in an explicit_const_any_regular_t to consume the one
531 // allowed implicit cast by the compiler, preventing an infinite recursion
532 // of T being converted to an any_regular_t and then attempting to re-
533 // serialize.
534 struct explicit_const_any_regular_t {
535 explicit_const_any_regular_t(const any_regular_t& x) : p_m(x) {}
536
537 const any_regular_t& p_m;
538 };
539
540 friend std::ostream& operator<<(std::ostream& out, const explicit_const_any_regular_t& value) {
541 value.p_m.object().serialize(out);
542
543 return out;
544 }
545#endif
546
547 friend bool operator==(const any_regular_t& x, const any_regular_t& y);
548 friend void swap(any_regular_t& x, any_regular_t& y);
549
550private:
551 any_regular_t(interface_type&& x) noexcept { x.move_clone(storage()); }
552
553 interface_type& object() { return *static_cast<interface_type*>(storage()); }
554 const interface_type& object() const { return *static_cast<const interface_type*>(storage()); }
555
556 void* storage() { return &data_m; }
557 const void* storage() const { return &data_m; }
558
559 storage_t data_m;
560
561#ifndef ADOBE_NO_DOCUMENTATION
562
563#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
564public:
565#else
566 template <typename, typename>
568#endif
569
570 template <typename T>
571 T* ptr_cast() {
572 return helper<T>::ptr_cast(*this);
573 }
574
575#endif
576};
577
578#ifndef ADOBE_NO_DOCUMENTATION
579
580static_assert(sizeof(any_regular_t) == 16);
581
582inline bool operator==(const any_regular_t& x, const any_regular_t& y) {
583 return (x.type_info() == y.type_info()) && x.object().equals(y.object());
584}
585
586inline void swap(any_regular_t& x, any_regular_t& y) {
587 any_regular_t::interface_type& a(x.object());
588 any_regular_t::interface_type& b(y.object());
589
590 if (a.type_info() == b.type_info()) {
591 a.exchange(b);
592 return;
593 }
594
595 // x->tmp
596 any_regular_t tmp = std::move(a);
597 a.destruct();
598
599 // y->x
600 b.move_clone(x.storage());
601 b.destruct();
602
603 // tmp->y
604 tmp.object().move_clone(y.storage());
605}
606
607#endif
608
609/**************************************************************************************************/
610
611#ifndef ADOBE_NO_DOCUMENTATION
612
613template <typename T>
614struct any_regular_t::helper {
615 static inline T* ptr_cast(any_regular_t& r) {
616 if (r.type_info() != typeid(T))
617 return 0;
618 return &reinterpret_cast<typename traits<T>::model_type&>(r.object()).get();
619 }
620
621 static inline typename traits<T>::const_result_type cast(const any_regular_t& r) {
622 typedef typename traits<T>::promote_type promote_type;
623
624 if (r.type_info() != typeid(promote_type))
625 throw bad_cast(r.type_info(), typeid(promote_type));
626 return static_cast<typename traits<T>::const_result_type>(
627 reinterpret_cast<const typename traits<T>::model_type&>(r.object()).get());
628 }
629
630 static inline typename traits<T>::result_type cast(any_regular_t& r) {
631 typedef typename traits<T>::promote_type promote_type;
632
633 if (r.type_info() != typeid(promote_type))
634 throw bad_cast(r.type_info(), typeid(promote_type));
635 return static_cast<typename traits<T>::result_type>(
636 reinterpret_cast<typename traits<T>::model_type&>(r.object()).get());
637 }
638
639 static inline any_regular_t& assign(any_regular_t& r, const T& x) {
640 typedef typename promote<T>::type promote_type;
641
642 if (r.type_info() == typeid(promote_type))
643 r.cast<promote_type>() = static_cast<promote_type>(x);
644 else {
645 any_regular_t result(x);
646 swap(r, result);
647 }
648 return r;
649 }
650};
651
652/**************************************************************************************************/
653
654template <>
655struct any_regular_t::helper<any_regular_t> {
656 static inline any_regular_t* ptr_cast(any_regular_t& r) { return &r; }
657
658 static inline const any_regular_t& cast(const any_regular_t& r) { return r; }
659
660 static inline any_regular_t& cast(any_regular_t& r) { return r; }
661};
662
663#endif
664
665/**************************************************************************************************/
666
667} // namespace version_1
668
669/**************************************************************************************************/
670
676
677inline bool empty(const any_regular_t& x) { return x.type_info() == typeid(empty_t); }
678
679/**************************************************************************************************/
680
684
685/**************************************************************************************************/
686
687template <typename R>
689 R operator()(const any_regular_t& x) const {
690 typedef typename boost::remove_const<typename boost::remove_reference<R>::type>::type
691 result_type;
692
693 static_assert(boost::is_reference<R>::value);
694
695 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
696 static_assert(std::is_same<typename promote<result_type>::type, result_type>::value);
697
698 return x.cast<result_type>();
699 }
700};
701
702/**************************************************************************************************/
703
704template <typename R>
707 typedef typename boost::remove_reference<R>::type result_type;
708
709 static_assert(boost::is_reference<R>::value);
710
711 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
712 static_assert(std::is_same<typename promote<result_type>::type, result_type>::value);
713
714 return x.cast<result_type>();
715 }
716};
717
718/**************************************************************************************************/
719
720template <typename R>
723 typedef typename boost::remove_pointer<R>::type result_type;
724
725 static_assert(boost::is_pointer<R>::value);
726
727 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
728 static_assert(std::is_same<typename promote<result_type>::type, result_type>::value);
729
730 return x->ptr_cast<result_type>();
731 }
732};
733
734/**************************************************************************************************/
735
736template <typename R>
737struct runtime_cast_t<R, const any_regular_t*> {
738 R operator()(const any_regular_t* x) const {
739 typedef
740 typename boost::remove_const<typename boost::remove_pointer<R>::type>::type result_type;
741
742 static_assert(boost::is_pointer<R>::value);
743
744 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
745 static_assert(std::is_same<typename promote<result_type>::type, result_type>::value);
746
747 if (x->type_info() != typeid(result_type))
748 return 0;
749 return &x->cast<result_type>();
750 }
751};
752
753/**************************************************************************************************/
754
755#ifndef NDEBUG
756
757void print(const any_regular_t& x);
758
759#endif
760
761/**************************************************************************************************/
762
763} // namespace adobe
764
765/**************************************************************************************************/
766
767#endif
768
769/**************************************************************************************************/
An exception class thrown during ASL failures to cast.
Definition typeinfo.hpp:33
A runtime polymorphic type similar to boost::any which can hold any type which models Regular.
traits< T >::result_type cast()
traits< T >::const_result_type cast() const
any_regular_t(const any_regular_t &x)
friend void swap(any_regular_t &x, any_regular_t &y)
const std::type_info & type_info() const
bool empty(const any_regular_t &x)
any_regular_t(any_regular_t &&x) noexcept
friend bool operator==(const any_regular_t &x, const any_regular_t &y)
any_regular_t & operator=(any_regular_t x)
any_regular_t & assign(any_regular_t x)
void swap(any_regular_t &x, any_regular_t &y)
bool operator==(const any_regular_t &x, const any_regular_t &y)
void destroy(T *p)
Definition memory.hpp:341
void print(const any_regular_t &x)
T * construct_at(T *p, Args &&... args)
Definition memory.hpp:350
std::ostream & operator<<(std::ostream &s, const extents_t &x)
std:: conditional_t< std::is_arithmetic_v< T > &&(2<=sizeof(T) &&sizeof(T)<=4), double, T > type
R operator()(const any_regular_t &x) const
static any_regular_t * ptr_cast(any_regular_t &r)
static const any_regular_t & cast(const any_regular_t &r)
static any_regular_t & cast(any_regular_t &r)
Function object used in binding for instance value access.
traits< T >::result_type operator()(any_regular_t &x) const
traits< T >::const_result_type operator()(const any_regular_t &x) const
An empty regular- and less-than-comparable- type.
Definition empty.hpp:42