wibble 0.1.28
amorph.h
Go to the documentation of this file.
00001 
00006 #include <iostream> // for noise
00007 
00008 #include <wibble/mixin.h>
00009 #include <wibble/cast.h>
00010 #include <wibble/maybe.h>
00011 #include <wibble/sfinae.h>
00012 #include <wibble/test.h>
00013 
00014 #ifndef WIBBLE_AMORPH_H
00015 #define WIBBLE_AMORPH_H
00016 
00017 namespace wibble {
00018 
00019 template< typename _T >
00020 struct ReturnType {
00021     typedef _T T;
00022 };
00023 
00024 template<>
00025 struct ReturnType< void > {
00026     typedef Unit T;
00027 };
00028 
00029 template< typename F, typename R >
00030 struct SanitizeReturn {
00031     inline typename ReturnType< R >::T call(
00032         typename F::argument_type a )
00033     {
00034         return f( a );
00035     };
00036 };
00037 
00038 
00039 template< typename F >
00040 struct SanitizeReturn< F, void > {
00041     inline Unit call( typename F::argument_type a )
00042     {
00043         f( a );
00044         return Unit();
00045     }
00046 };
00047 
00048 template< int A >
00049 struct IsZero {
00050     static const bool value = false;
00051 };
00052 
00053 template<>
00054 struct IsZero< 0 > {
00055     static const bool value = true;
00056 };
00057 
00058 template< typename T >
00059 struct IsPolymorphic {
00060     struct A : T {
00061         virtual ~A();
00062     };
00063     struct B : T {};
00064     static const bool value = IsZero< sizeof( A ) - sizeof( B ) >::value;
00065 };
00066 
00067 template< typename F >
00068 struct SanitizeResultType {
00069     SanitizeResultType( F _f ) : f( _f ) {}
00070     typedef typename ReturnType< typename F::result_type >::T result_type;
00071 
00072     result_type operator()( typename F::argument_type a ) {
00073         return SanitizeReturn< F, typename F::result_type >().call( a );
00074     }
00075 
00076 
00077     F f;
00078 };
00079 
00080 #ifndef SWIG_I
00081 struct Baseless {};
00082 
00083 struct VirtualBase {
00084     virtual ~VirtualBase() {}
00085 };
00086 
00090 template< typename Interface >
00091 struct MorphInterface : public Interface {
00092     virtual VirtualBase *virtualBase() { return 0; }
00093     virtual MorphInterface *constructCopy( void *where = 0, unsigned int available = 0 ) const = 0;
00094     virtual void destroy( unsigned int available = 0 ) = 0;
00095     virtual ~MorphInterface() {}
00096     virtual bool leq( const MorphInterface * ) const = 0;
00097 };
00098 
00100 struct MorphAllocator {
00101     void *operator new( size_t bytes, void *where, unsigned available ) {
00102         if ( bytes > available || where == 0 ) {
00103             where = ::operator new( bytes );
00104             return where;
00105         }
00106         return where;
00107     }
00108     void *operator new( size_t bytes ) {
00109         return ::operator new( bytes );
00110     }
00111 };
00112 
00113 template< typename W, typename Interface >
00114 struct MorphBase : MorphInterface< Interface > {
00115     MorphBase( const W &w ) : m_wrapped( w ) {}
00116 
00117     template< typename _W >
00118     typename EnableIf< IsPolymorphic< _W >, VirtualBase *>::T virtualBase() {
00119         return dynamic_cast< VirtualBase * >( &m_wrapped );
00120     }
00121 
00122     template< typename _W >
00123     typename EnableIf< TNot< IsPolymorphic< _W > >, VirtualBase *>::T
00124     virtualBase() {
00125         return 0;
00126     }
00127 
00128     virtual VirtualBase *virtualBase() {
00129         return virtualBase< W >();
00130     }
00131 
00132     W &wrapped() {
00133         return m_wrapped;
00134     }
00135 
00136 protected:
00137     W m_wrapped;
00138 };
00139 
00140 template< typename Self, typename W, typename Interface >
00141 struct Morph : MorphBase< W, Interface >,
00142     mixin::Comparable< Morph< Self, W, Interface > >,
00143     MorphAllocator
00144 {
00145     typedef W Wrapped;
00146 
00147     Morph( const Wrapped &w ) : MorphBase< W, Interface >( w ) {}
00148 
00149     const Self &self() const { return *static_cast< const Self * >( this ); }
00150 
00151     bool operator<=( const Morph &o ) const {
00152         return wrapped().operator<=( o.wrapped() );
00153     }
00154 
00155     // evaluation of correctness of definition should be done
00156     virtual bool leq( const MorphInterface< Interface > *_o ) const {
00157         const Morph *o = dynamic_cast< const Morph * >( _o );
00158         if ( !o ) {
00159             if ( typeid( Morph ).before( typeid( _o ) ) )
00160                 return true;
00161             else
00162                 return false;
00163         }
00164         return wrapped() <= o->wrapped();
00165     }
00166 
00167     virtual MorphInterface< Interface > *constructCopy(
00168         void *where, unsigned int available ) const
00169     {
00170         return new( where, available ) Self( self() );
00171     }
00172 
00173     virtual void destroy( unsigned int available ) {
00174         if ( sizeof( Morph ) <= available ) {
00175             this->~Morph();
00176         } else {
00177             delete this;
00178         }
00179     }
00180 
00181     const Wrapped &wrapped() const {
00182         return this->m_wrapped;
00183     }
00184 
00185     Wrapped &wrapped() {
00186         return this->m_wrapped;
00187     }
00188 
00189     virtual ~Morph() {}
00190 };
00191 #endif
00192 
00260 #ifndef WIBBLE_AMORPH_PADDING
00261 #define WIBBLE_AMORPH_PADDING 0
00262 #endif
00263 template<int Padding1> class AmorphPadder
00264 {
00265     int m_padding[ Padding1 ];
00266 };
00267 template<> class AmorphPadder<0>
00268 {
00269 };
00270 
00271 template< typename Self, typename _Interface, int Padding = WIBBLE_AMORPH_PADDING >
00272 struct Amorph {
00273     typedef _Interface Interface;
00274     // typedef MorphInterface< Interface > Morp;
00275 
00276     template <typename T> struct Convert {
00277         typedef T type;
00278     };
00279 
00280     /* Amorph( const Interface &b ) {
00281         setInterfacePointer( &b );
00282         } */
00283 
00284     Amorph( const MorphInterface< Interface > &b ) {
00285         setMorphInterfacePointer( &b );
00286     }
00287 
00288     Amorph( const Amorph &a ) {
00289         setMorphInterfacePointer( a.morphInterface() );
00290         // setInterfacePointer( a.implementation() );
00291     }
00292 
00293     Amorph() : m_impl( 0 ) {}
00294 
00295     const Self &self() const {
00296         return *static_cast< const Self * >( this );
00297     }
00298 
00299     Self &self() {
00300         return *static_cast<Self *>( this );
00301     }
00302 
00303     bool leq( const Self &i ) const {
00304         if ( morphInterface() )
00305             if ( i.morphInterface() )
00306                 return morphInterface()->leq( i.morphInterface() );
00307             else
00308                 return false; // it's false that non-0 <= 0
00309         else
00310             return !i.morphInterface(); // 0 <= 0 holds, but 0 <=
00311                                         // non-0 doesn't
00312     }
00313 
00314     bool operator<=( const Self &i ) const { return leq( i ); }
00315 
00316     void setInterfacePointer( const Interface *i ) {
00317         if ( !i ) {
00318             m_impl = 0;
00319             return;
00320         }
00321 
00322         /* assert( dynamic_cast< const MorphInterface * >( i ) );
00323         assert( dynamic_cast< const Interface * >(
00324         dynamic_cast< const MorphInterface * >( i ) ) ); */
00325 
00326         m_impl = dynamic_cast< const MorphInterface< Interface > * >( i )->constructCopy(
00327             &m_padding, sizeof( m_padding ) );
00328 
00329         // assert( dynamic_cast< const Interface * >( m_impl ) );
00330     }
00331 
00332     void setMorphInterfacePointer( const MorphInterface< Interface > *i ) {
00333         if ( !i ) {
00334             m_impl = 0;
00335             return;
00336         }
00337         m_impl = i->constructCopy( &m_padding, sizeof( m_padding ) );
00338     }
00339 
00340     Amorph &operator=( const Amorph &i ) {
00341         setInterfacePointer( i.implementation() );
00342         return *this;
00343     }
00344 
00345     ~Amorph() {
00346         if ( morphInterface() )
00347             morphInterface()->destroy( sizeof( m_padding ) );
00348     }
00349 
00350     template< typename F >
00351     Maybe< typename F::result_type > ifType( F func ) {
00352         typedef typename F::argument_type T;
00353         typedef Maybe< typename F::result_type > rt;
00354         T *ptr = impl<T>();
00355         if (ptr) {
00356             return rt::Just( func(*ptr) );
00357         }
00358         return rt::Nothing();
00359     }
00360 
00361     const Interface *implementation() const {
00362         // return dynamic_cast< const Interface * >( m_impl );
00363         return static_cast< const Interface * >( m_impl );
00364     }
00365 
00366     Interface *implementation() {
00367         // return dynamic_cast< Interface * >( m_impl );
00368         return static_cast< Interface * >( m_impl );
00369     }
00370 
00371     MorphInterface< Interface > *morphInterface() const {
00372         return m_impl;
00373         // return dynamic_cast< MorphInterface< * >( m_impl );
00374     }
00375 
00376     const Interface &wrapped() const {
00377         return *implementation();
00378     }
00379 
00380     Interface &wrapped() {
00381         return *implementation();
00382     }
00383 
00384     template< typename T >
00385     bool is() const {
00386         return impl< T >();
00387     }
00388 
00389     bool isVoid() const { return !m_impl; }
00390 
00391     template< typename T >
00392     T *impl() const {
00393         T *p = dynamic_cast< T * >( m_impl );
00394         if ( !p ) {
00395             MorphBase< T, Interface > *m = dynamic_cast< MorphBase< T, Interface > * >( m_impl );
00396             if ( m ) p = &(m->wrapped());
00397         }
00398         if ( !p ) {
00399             p = dynamic_cast< T * >( morphInterface()->virtualBase() );
00400         }
00401         return p;
00402     }
00403 
00404 private:
00405     unsigned int reservedSize() { return sizeof( m_padding ) + sizeof( m_impl ); }
00406     AmorphPadder<Padding> m_padding;
00407     MorphInterface< Interface > *m_impl;
00408     // Interface *m_impl;
00409 };
00410 
00411 #ifndef SWIG_I
00412 template< typename T, typename X >
00413 typename X::template Convert<T>::type &downcast( const X &a )
00414 {
00415     return *a.template impl< T >();
00416 }
00417 
00418 #endif
00419 
00420 }
00421 
00422 #endif