stlab.adobe.com Adobe Systems Incorporated
any_regular.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3  Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
4  or a copy at http://stlab.adobe.com/licenses.html)
5 */
6 
7 /**************************************************************************************************/
8 
9 
10 #ifndef ADOBE_ANY_REGULAR_HPP
11 #define ADOBE_ANY_REGULAR_HPP
12 
13 #include <adobe/config.hpp>
14 
16 
17 #include <boost/mpl/bool.hpp>
18 #include <boost/mpl/if.hpp>
19 #include <boost/noncopyable.hpp>
20 #include <boost/operators.hpp>
21 #include <boost/static_assert.hpp>
22 #include <boost/type_traits/has_nothrow_copy.hpp>
23 #include <boost/type_traits/is_pointer.hpp>
24 #include <boost/type_traits/is_reference.hpp>
25 #include <boost/type_traits/is_same.hpp>
26 #include <boost/type_traits/remove_const.hpp>
27 #include <boost/type_traits/remove_pointer.hpp>
28 #include <boost/type_traits/remove_reference.hpp>
29 #include <boost/concept_check.hpp>
30 
31 #include <adobe/conversion.hpp>
32 #include <adobe/cstdint.hpp>
33 #include <adobe/empty.hpp>
34 #include <adobe/memory.hpp>
35 #include <adobe/move.hpp>
36 #include <adobe/typeinfo.hpp>
38 
39 #include <adobe/implementation/swap.hpp>
40 
41 #if defined(ADOBE_STD_SERIALIZATION)
42 #include <iosfwd>
43 #endif
44 
45 /**************************************************************************************************/
46 
47 namespace adobe {
48 
150 /**************************************************************************************************/
151 
152 namespace implementation {
153 
154 enum { vtable_version = 1 };
155 
156 struct any_regular_interface_t;
157 
158 struct vtable_t
159 {
160  typedef any_regular_interface_t interface_type;
161 
162  adobe::uintptr_t version;
163  void (*destruct)(const interface_type&);
164  type_info_t (*type_info)(const interface_type&);
165  interface_type* (*clone)(const interface_type&, void*);
166  interface_type* (*move_clone)(interface_type&, void*);
167  void (*assign)(interface_type&, const interface_type&);
168  bool (*equals)(const interface_type&, const interface_type&);
169  void (*exchange)(interface_type&, interface_type&);
170 };
171 
172 // Ensure that the vtable_t has a fixed layout regardless of alignment or packing.
173 
174 BOOST_STATIC_ASSERT(sizeof(vtable_t) == 8 * sizeof(void*));
175 
176 /**************************************************************************************************/
177 
178 union pad_vtable_t
179 {
180  const vtable_t* vtable_m;
181  double pad_m; // unused padding
182 };
183 
184 BOOST_STATIC_ASSERT(sizeof(pad_vtable_t) == sizeof(double));
185 
186 /**************************************************************************************************/
187 
188 struct any_regular_interface_t {
189  typedef any_regular_interface_t interface_type;
190 
191  any_regular_interface_t(const vtable_t& x) { object_m.vtable_m = &x; }
192 
193  pad_vtable_t object_m;
194 
195  void destruct() const { return object_m.vtable_m->destruct(*this); }
196  type_info_t type_info() const { return object_m.vtable_m->type_info(*this); }
197  interface_type* clone(void* x) const { return object_m.vtable_m->clone(*this, x); }
198  interface_type* move_clone(void* x) { return object_m.vtable_m->move_clone(*this, x); }
199  void assign(const interface_type& x) { object_m.vtable_m->assign(*this, x); }
200  bool equals(const interface_type& x) const { return object_m.vtable_m->equals(*this, x); }
201  void exchange(interface_type& x) { object_m.vtable_m->exchange(*this, x); }
202 };
203 
204 /**************************************************************************************************/
205 
206 template <typename T> // T models Regular
207 struct any_regular_model_local : any_regular_interface_t, boost::noncopyable
208 {
209  typedef any_regular_interface_t interface_type;
210 
211  T object_m;
212 
213  static const vtable_t vtable_s;
214 
215  any_regular_model_local() : interface_type(vtable_s), object_m() { }
216 
217  explicit any_regular_model_local(T x)
218  : interface_type(vtable_s), object_m(adobe::move(x)) { }
219 
220  static const any_regular_model_local& self(const interface_type& x)
221  { return static_cast<const any_regular_model_local&>(x); }
222 
223  static any_regular_model_local& self(interface_type& x)
224  { return static_cast<any_regular_model_local&>(x); }
225 
226  static type_info_t type_info(const interface_type&)
227  { return adobe::type_info<T>(); }
228 
229  static void destruct(const interface_type& x)
230  { self(x).~any_regular_model_local(); }
231 
232  static interface_type* clone(const interface_type& x, void* storage)
233  { return ::new(storage) any_regular_model_local(self(x).object_m); }
234 
235  static interface_type* move_clone(interface_type& x, void* storage)
236  { return ::new(storage) any_regular_model_local(adobe::move(self(x).object_m)); }
237 
238  static void assign(interface_type& x, const interface_type& y)
239  { self(x).object_m = self(y).object_m; }
240 
241  static bool equals(const interface_type& x, const interface_type& y)
242  { return self(x).object_m == self(y).object_m; }
243 
244  static void exchange(interface_type& x, interface_type& y)
245  { swap(self(x).object_m, self(y).object_m); }
246 
247  const T& get() const { return object_m; }
248  T& get() { return object_m; }
249 };
250 
251 BOOST_STATIC_ASSERT(sizeof(any_regular_model_local<double>) == 16);
252 
253 template <typename T>
254 const vtable_t any_regular_model_local<T>::vtable_s
255  = {
256 #ifndef NDEBUG
257  short_name<T>::value,
258 #else
259  vtable_version,
260 #endif
261  &any_regular_model_local::destruct,
263  &any_regular_model_local::clone,
264  &any_regular_model_local::move_clone,
265  &any_regular_model_local::assign,
266  &any_regular_model_local::equals,
267  &any_regular_model_local::exchange,
268  };
269 
270 template <typename T> // T models Regular
271 struct any_regular_model_remote : any_regular_interface_t, boost::noncopyable
272 {
273  BOOST_CLASS_REQUIRE(T, adobe, RegularConcept);
274 
275  typedef any_regular_interface_t interface_type;
276 
277  struct object_t;
278  typedef capture_allocator<object_t> allocator_type;
279 
280  struct object_t : boost::noncopyable
281  {
282  aligned_storage<allocator_type> alloc_m;
283  T data_m;
284  };
285 
286  static object_t* new_move(T& x)
287  {
288  allocator_type a;
289  object_t* result = a.allocate(1);
290  construct(&result->alloc_m, aligned_storage<allocator_type>(a));
291  construct(&result->data_m, adobe::move(x));
292  return result;
293  }
294 
295  object_t* object_ptr_m;
296 
297  static const vtable_t vtable_s;
298 
299  explicit any_regular_model_remote(T x)
300  : interface_type(vtable_s), object_ptr_m(new_move(x))
301  { }
302 
303  any_regular_model_remote(move_from<any_regular_model_remote> x)
304  : interface_type(vtable_s), object_ptr_m(x.source.object_ptr_m) { x.source.object_ptr_m = 0; }
305 
306  ~any_regular_model_remote()
307  {
308  if (object_ptr_m) {
309  allocator_type a = object_ptr_m->alloc_m.get();
310  destroy(&object_ptr_m->alloc_m);
311  destroy(&object_ptr_m->data_m);
312  a.deallocate(object_ptr_m, 1);
313  }
314  }
315 
316  static const any_regular_model_remote& self(const interface_type& x)
317  { return static_cast<const any_regular_model_remote&>(x); }
318 
319  static any_regular_model_remote& self(interface_type& x)
320  { return static_cast<any_regular_model_remote&>(x); }
321 
322  static type_info_t type_info(const interface_type&)
323  { return adobe::type_info<T>(); }
324 
325  static void destruct(const interface_type& x)
326  { return self(x).~any_regular_model_remote(); }
327 
328  static interface_type* clone(const interface_type& x, void* storage)
329  { return ::new(storage) any_regular_model_remote(self(x).get()); }
330 
331  static interface_type* move_clone(interface_type& x, void* storage)
332  { return ::new(storage) any_regular_model_remote(move_from<any_regular_model_remote>(self(x))); }
333 
334  static void assign(interface_type& x, const interface_type& y)
335  { self(x).get() = self(y).get(); }
336 
337  static bool equals(const interface_type& x, const interface_type& y)
338  { return self(x).get() == self(y).get(); }
339 
340  static void exchange(interface_type& x, interface_type& y)
341  { return swap(self(x).object_ptr_m, self(y).object_ptr_m); }
342 
343  const T& get() const { return object_ptr_m->data_m; }
344  T& get() { return object_ptr_m->data_m; }
345 };
346 
347 BOOST_STATIC_ASSERT(sizeof(any_regular_model_remote<double>) <= 16);
348 
349 template <typename T>
350 const vtable_t any_regular_model_remote<T>::vtable_s
351  = {
352 #ifndef NDEBUG
353  short_name<T>::value,
354 #else
355  vtable_version,
356 #endif
357  &any_regular_model_remote::destruct,
359  &any_regular_model_remote::clone,
360  &any_regular_model_remote::move_clone,
361  &any_regular_model_remote::assign,
362  &any_regular_model_remote::equals,
363  &any_regular_model_remote::exchange,
364  };
365 
366 /**************************************************************************************************/
367 
368 } // namespace implementation
369 
370 /**************************************************************************************************/
371 
372 namespace version_1 {
373 
374 /**************************************************************************************************/
375 
426 class any_regular_t : boost::equality_comparable<any_regular_t, any_regular_t>
427 {
428  typedef implementation::any_regular_interface_t interface_type;
429  typedef double storage_t[2];
430 
431  #ifndef ADOBE_NO_DOCUMENTATION
432 
433  template <typename T>
434  struct traits
435  {
436  typedef typename promote<T>::type promote_type;
437  BOOST_CLASS_REQUIRE(promote_type, adobe, RegularConcept);
438 
439  typedef promote_type& reference_type;
440  typedef const promote_type& const_reference_type;
441 
442  typedef implementation::any_regular_model_local<promote_type> regular_model_local_type;
443  typedef implementation::any_regular_model_remote<promote_type> regular_model_remote_type;
444 
445  typedef boost::mpl::bool_<(sizeof(regular_model_local_type)
446  <= sizeof(storage_t))
447  && (boost::has_nothrow_copy<promote_type>::value
448  || is_movable<promote_type>::value)> use_local_type;
449 
450  typedef typename boost::mpl::if_<use_local_type,
451  regular_model_local_type,
452  regular_model_remote_type>::type model_type;
453 
454  typedef typename boost::mpl::if_c<
455  boost::is_same<promote_type, T>::value,
456  reference_type, T>::type result_type;
457 
458  typedef typename boost::mpl::if_c<
459  boost::is_same<promote_type, T>::value,
460  const_reference_type, T>::type const_result_type;
461  };
462 
463  template <typename T> struct helper;
464  template <typename T> friend struct helper;
465 
466  #endif
467 
468  public:
475  any_regular_t() { ::new (storage()) traits<empty_t>::model_type(); }
476 
477  any_regular_t(const any_regular_t& x) { x.object().clone(storage()); }
478 
479  any_regular_t(move_from<any_regular_t> x) { x.source.object().move_clone(storage()); }
480 
482  {
483  object().destruct();
484  x.object().move_clone(storage());
485  return *this;
486  }
487 
488  ~any_regular_t() { object().destruct(); }
497  template <typename T>
498  explicit any_regular_t(T x)
499  { ::new (storage()) typename traits<T>::model_type(adobe::move(x)); }
500 
514  template <typename T>
515  bool cast(T& x) const
516  {
517  if (type_info() != adobe::type_info<typename promote<T>::type>()) return false;
518  x = cast<T>();
519  return true;
520  }
521 
522  template <typename T>
523  typename traits<T>::const_result_type cast() const
524  { return helper<T>::cast(*this); }
525 
535  template <typename T>
536  typename traits<T>::result_type cast()
537  { return helper<T>::cast(*this); }
538 
552  template <typename T>
554  {
555  object().destruct();
556  ::new (storage()) typename traits<T>::model_type(adobe::move(x));
557  return *this;
558  }
559 
561  {
562  object().destruct();
563  x.object().move_clone(storage());
564  return *this;
565  }
566 
576  type_info_t type_info() const { return object().type_info(); }
577 
585  template <typename T>
586  struct transform
587  {
588  typedef typename traits<T>::promote_type result_type;
589 
590  typename traits<T>::result_type operator () (any_regular_t& x) const
591  { return x.cast<T>(); }
592 
593  typename traits<T>::const_result_type operator () (const any_regular_t& x) const
594  { return x.cast<T>(); }
595  };
596 
597 #if defined(ADOBE_STD_SERIALIZATION)
598  friend std::ostream& operator<<(std::ostream& out, const any_regular_t& value);
599 #endif
600 
601  friend bool operator==(const any_regular_t& x, const any_regular_t& y);
602  friend void swap(any_regular_t& x, any_regular_t& y);
603 
604  private:
605  any_regular_t(move_from<interface_type> x) { x.source.move_clone(storage()); }
606 
607  interface_type& object() { return *static_cast<interface_type*>(storage()); }
608  const interface_type& object() const { return *static_cast<const interface_type*>(storage()); }
609 
610  void* storage() { return &data_m; }
611  const void* storage() const { return &data_m; }
612 
613  storage_t data_m;
614 
615 #ifndef ADOBE_NO_DOCUMENTATION
616 
617 #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
618 public:
619 #else
620  template <typename, typename> friend struct adobe::runtime_cast_t;
621 #endif
622 
623  template <typename T>
624  T* ptr_cast()
625  { return helper<T>::ptr_cast(*this); }
626 
627 #endif
628 };
629 
630 #ifndef ADOBE_NO_DOCUMENTATION
631 
632 BOOST_STATIC_ASSERT((sizeof(any_regular_t) == 16));
633 
634 inline bool operator == (const any_regular_t& x, const any_regular_t& y)
635 { return (x.type_info() == y.type_info()) && x.object().equals(y.object()); }
636 
637 inline void swap(any_regular_t& x, any_regular_t& y)
638 {
639  any_regular_t::interface_type& a(x.object());
640  any_regular_t::interface_type& b(y.object());
641 
642  if (a.type_info() == b.type_info()) { a.exchange(b); return; }
643 
644  // x->tmp
645  any_regular_t tmp((move_from<any_regular_t::interface_type>(a)));
646  a.destruct();
647 
648  // y->x
649  b.move_clone(x.storage());
650  b.destruct();
651 
652  // tmp->y
653  tmp.object().move_clone(y.storage());
654 }
655 
656 #endif
657 
658 /**************************************************************************************************/
659 
660 #ifndef ADOBE_NO_DOCUMENTATION
661 
662 template <typename T>
663 struct any_regular_t::helper
664 {
665  static inline T* ptr_cast(any_regular_t& r)
666  {
667  if (r.type_info() != adobe::type_info<T>())
668  return 0;
669  return &reinterpret_cast<typename traits<T>::model_type&>(r.object()).get();
670  }
671 
672  static inline typename traits<T>::const_result_type cast(const any_regular_t& r)
673  {
674  typedef typename traits<T>::promote_type promote_type;
675 
676  if (r.type_info() != adobe::type_info<promote_type>())
677  throw bad_cast(r.type_info(), adobe::type_info<promote_type>());
678  return static_cast<typename traits<T>::const_result_type>(
679  reinterpret_cast<const typename traits<T>::model_type&>(r.object()).get());
680  }
681 
682  static inline typename traits<T>::result_type cast(any_regular_t& r)
683  {
684  typedef typename traits<T>::promote_type promote_type;
685 
686  if (r.type_info() != adobe::type_info<promote_type>())
687  throw bad_cast(r.type_info(), adobe::type_info<promote_type>());
688  return static_cast<typename traits<T>::result_type>(
689  reinterpret_cast<typename traits<T>::model_type&>(r.object()).get());
690  }
691 
692  static inline any_regular_t& assign(any_regular_t& r, const T& x)
693  {
694  typedef typename promote<T>::type promote_type;
695 
696  if (r.type_info() == adobe::type_info<promote_type>())
697  r.cast<promote_type>() = static_cast<promote_type>(x);
698  else
699  {
700  any_regular_t result(x);
701  swap(r, result);
702  }
703  return r;
704  }
705 };
706 
707 /**************************************************************************************************/
708 
709 template <>
710 struct any_regular_t::helper<any_regular_t>
711 {
712  static inline any_regular_t* ptr_cast(any_regular_t& r)
713  { return &r; }
714 
715  static inline const any_regular_t& cast(const any_regular_t& r)
716  { return r; }
717 
718  static inline any_regular_t& cast(any_regular_t& r)
719  { return r; }
720 };
721 
722 #endif
723 
724 /**************************************************************************************************/
725 
726 } // namespace version_1
727 
728 /**************************************************************************************************/
729 
736 inline bool empty(const any_regular_t& x) { return x.type_info() == type_info<empty_t>(); }
737 
738 /**************************************************************************************************/
739 
744 /**************************************************************************************************/
745 
746 template <typename R>
748 {
749  R operator()(const any_regular_t& x) const
750  {
751  typedef typename boost::remove_const<typename boost::remove_reference<R>::type>::type
752  result_type;
753 
754  BOOST_STATIC_ASSERT((boost::is_reference<R>::value));
755 
756  /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
757  BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
758 
759  return x.cast<result_type>();
760  }
761 };
762 
763 /**************************************************************************************************/
764 
765 template <typename R>
767 {
768  R operator()(any_regular_t& x) const
769  {
770  typedef typename boost::remove_reference<R>::type result_type;
771 
772  BOOST_STATIC_ASSERT((boost::is_reference<R>::value));
773 
774  /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
775  BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
776 
777  return x.cast<result_type>();
778  }
779 };
780 
781 /**************************************************************************************************/
782 
783 template <typename R>
785 {
786  R operator()(any_regular_t* x) const
787  {
788  typedef typename boost::remove_pointer<R>::type result_type;
789 
790  BOOST_STATIC_ASSERT((boost::is_pointer<R>::value));
791 
792  /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
793  BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
794 
795  return x->ptr_cast<result_type>();
796  }
797 };
798 
799 /**************************************************************************************************/
800 
801 template <typename R>
802 struct runtime_cast_t<R, const any_regular_t*>
803 {
804  R operator()(const any_regular_t* x) const
805  {
806  typedef typename boost::remove_const<typename boost::remove_pointer<R>::type>::type
807  result_type;
808 
809  BOOST_STATIC_ASSERT((boost::is_pointer<R>::value));
810 
811  /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
812  BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
813 
814  if (x->type_info() != type_info<result_type>()) return 0;
815  return &x->cast<result_type>();
816  }
817 };
818 
819 /**************************************************************************************************/
820 
821 } // namespace adobe
822 
823 /**************************************************************************************************/
824 
825 ADOBE_NAME_TYPE_0("any_regular_t:version_1:adobe", adobe::version_1::any_regular_t)
826 
827 /**************************************************************************************************/
828 
829 #endif
830 
831 /**************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google