10 #define ADOBE_POLY_HPP
15 #include <boost/type_traits/is_base_of.hpp>
16 #include <boost/type_traits/remove_reference.hpp>
17 #include <boost/type_traits/remove_pointer.hpp>
18 #include <boost/utility/enable_if.hpp>
19 #include <boost/mpl/or.hpp>
20 #include <boost/mpl/if.hpp>
21 #include <boost/mpl/bool.hpp>
22 #include <boost/type_traits/has_nothrow_constructor.hpp>
25 #include <adobe/implementation/swap.hpp>
48 #if !defined(ADOBE_NO_DOCUMENTATION)
50 template <
typename T,
typename U>
51 struct is_base_derived_or_same : boost::mpl::or_<boost::is_base_of<T, U>,
52 boost::is_base_of<U, T>,
53 boost::is_same<T, U> > {};
69 virtual void*
cast() = 0;
70 virtual const void*
cast()
const = 0;
73 #ifndef NO_ASL_AI_CONCEPT_CHECK
86 #if !defined(ADOBE_NO_DOCUMENTATION)
90 namespace implementation {
94 template <
typename ConcreteType,
typename Interface>
95 struct poly_state_remote : Interface
97 typedef ConcreteType value_type;
98 typedef Interface interface_type;
100 const value_type&
get()
const {
return *value_ptr_m; }
101 value_type&
get() {
return *value_ptr_m; }
103 poly_state_remote(move_from<poly_state_remote> x)
104 : value_ptr_m(x.source.value_ptr_m){ x.source.value_ptr_m = NULL; }
106 explicit poly_state_remote(value_type x)
107 : value_ptr_m(::new value_type(adobe::
move(x))) { }
110 {
delete value_ptr_m; }
112 #ifndef NO_ASL_AI_CONCEPT_CHECK
114 void assign(
const poly_copyable_interface& x)
115 { *value_ptr_m = *
static_cast<const poly_state_remote&
>(x).value_ptr_m; }
119 {
return typeid(value_type); }
120 const void* cast()
const {
return value_ptr_m; }
121 void* cast() {
return value_ptr_m; }
124 void exchange(poly_copyable_interface& x)
125 {
return std::swap(value_ptr_m, static_cast<poly_state_remote&>(x).value_ptr_m); }
128 friend bool operator==(
const poly_state_remote& x,
const poly_state_remote& y)
129 {
return *x.value_ptr_m == *y.value_ptr_m; }
131 value_type* value_ptr_m;
136 template <
typename ConcreteType,
typename Interface>
137 struct poly_state_local : Interface
139 typedef ConcreteType value_type;
140 typedef Interface interface_type;
142 const value_type&
get()
const {
return value_m; }
143 value_type&
get() {
return value_m; }
145 poly_state_local(move_from<poly_state_local> x)
146 : value_m(adobe::
move(x.source.value_m)){ }
148 explicit poly_state_local(value_type x)
149 : value_m(adobe::
move(x)) { }
151 #ifndef NO_ASL_AI_CONCEPT_CHECK
153 void assign(
const poly_copyable_interface& x)
154 { value_m =
static_cast<const poly_state_local&
>(x).value_m; }
158 {
return typeid(value_type); }
159 const void* cast()
const {
return &value_m; }
160 void* cast() {
return &value_m; }
163 void exchange(poly_copyable_interface& x)
164 {
return std::swap(value_m, static_cast<poly_state_local&>(x).value_m); }
167 friend bool operator==(
const poly_state_local& x,
const poly_state_local& y)
168 {
return x.value_m == y.value_m; }
176 typedef double storage_t[2];
178 template<
typename T,
int N=sizeof(storage_t)>
181 enum { value =
sizeof(T) <= N && (boost::has_nothrow_constructor<typename T::value_type>::value ||
182 boost::is_same<std::string, typename T::value_type>::value) };
188 template <
typename F>
189 struct poly_instance : F {
190 typedef typename F::value_type value_type;
191 typedef typename F::interface_type interface_type;
193 poly_instance(
const value_type& x): F(x){ }
194 poly_instance(move_from<poly_instance> x) : F(move_from<F>(x.source)) { }
196 poly_copyable_interface* clone(
void* storage)
const
197 { return ::new (storage) poly_instance(this->get()); }
199 poly_copyable_interface* move_clone(
void* storage)
200 { return ::new (storage) poly_instance(move_from<poly_instance>(*this)); }
205 template <typename T>
207 typedef bool (T::*E)(
const T&)
const;
208 typedef char (&no_type)[1];
209 typedef char (&yes_type)[2];
210 template <E e>
struct sfinae {
typedef yes_type type; };
212 static typename sfinae<&U::equals>::type
test(
int);
214 static no_type
test(...);
216 enum {value =
sizeof(test<T>(1)) ==
sizeof(yes_type)};
237 template <
typename ConcreteType,
typename Interface>
239 boost::mpl::if_<implementation::is_small<implementation::poly_state_local<ConcreteType, Interface> >,
240 implementation::poly_state_local<ConcreteType, Interface>,
241 implementation::poly_state_remote<ConcreteType, Interface> > {
258 template <
typename I,
template <
typename>
class Instance>
261 template <
typename T,
template <
typename>
class U>
268 template <
typename T>
270 typename boost::disable_if<boost::is_base_of<poly_base, T> >::type* = 0)
271 { ::new (storage()) implementation::poly_instance<Instance<T> >(
adobe::move(x)); }
274 template <
typename J,
template <
typename>
class K>
276 typename boost::enable_if<is_base_derived_or_same<I, J> >::type* dummy = 0)
278 if(boost::is_base_of<J, I>::value)
292 if (a.type_info() == b.type_info()) { a.
exchange(b);
return; }
308 interface_ref().~interface_type();
314 template <
typename J,
template <
typename>
class K>
320 template <
typename J>
327 {
return interface_ref().type_info(); }
329 template <
typename T>
const T&
cast()
const
333 return *
static_cast<const T*
>(interface_ref().cast());
336 template <
typename T> T&
cast()
340 return *
static_cast<T*
>(interface_ref().cast());
343 template <
typename T>
bool cast(T& x)
const
351 #ifndef NO_ASL_AI_CONCEPT_CHECK
365 template <
typename J,
template <
typename>
class K>
366 typename boost::enable_if<is_base_derived_or_same<I, J> >::type
369 if(boost::is_base_of<J, I>::value)
370 dynamic_cast<I&
>(
static_cast<J&
>(*x.interface_ptr()));
371 interface_ref().~interface_type();
377 {
return &interface_ref(); }
380 {
return &interface_ref(); }
389 const void*
storage()
const {
return &data_m; }
395 template <
class J,
template <
typename>
class K>
396 inline typename boost::enable_if<implementation::has_equals<J>,
bool>::type
422 template <
typename T>
423 explicit poly(
const T& x) : F(x) {}
448 template <
typename T,
typename U>
451 typedef typename boost::remove_reference<T>::type target_type;
452 typedef typename target_type::interface_type target_interface_type;
453 if(!x.template is_dynamic_convertible_to<target_interface_type>())
455 return reinterpret_cast<T
>(x);
467 template <
typename T,
typename U>
470 typedef typename boost::remove_reference<T>::type target_type;
471 typedef typename target_type::interface_type target_interface_type;
472 if(!x.template is_dynamic_convertible_to<target_interface_type>())
474 return reinterpret_cast<T
>(x);
494 template <
typename T,
typename U>
497 typedef typename boost::remove_pointer<T>::type target_type;
498 typedef typename target_type::interface_type target_interface_type;
499 return x->template is_dynamic_convertible_to<target_interface_type>()
500 ? reinterpret_cast<T>(x)
514 template <
typename T,
typename U>
517 typedef typename boost::remove_pointer<T>::type target_type;
518 typedef typename target_type::interface_type target_interface_type;
519 return x->template is_dynamic_convertible_to<target_interface_type>()
520 ? reinterpret_cast<T>(x)